JUC——创建线程的方法

​1. 继承 Thread 类​

​原理​:

  • 通过继承 Thread 类并重写其 run() 方法,定义线程的执行逻辑。(Thread类实现了Runnable接口
  • 调用 start() 方法启动线程(JVM 会自动调用 run())。

​特点​

  • ​简单直接​​,适合快速实现线程逻辑。

​局限性​​:Java 是单继承的,继承 Thread 后无法再继承其他类。

// 1. 继承 Thread 类
class MyThread extends Thread {
    @Override
    public void run() {
        System.out.println("线程执行: " + Thread.currentThread().getName());
    }
}

public class ThreadExample {
    public static void main(String[] args) {
        MyThread thread = new MyThread(); // 创建线程对象
        thread.start(); // 启动线程(调用 run())
    }
}

​2. 实现 Runnable 接口​

原理​:

  • 通过实现 Runnable 接口的 run() 方法定义线程逻辑。
  • 将 Runnable 实例传递给 Thread 对象,由 Thread 负责启动线程。

特点:

  • ​避免单继承限制​​,适合需要继承其他类的场景。
  • ​更灵活​​,同一个 Runnable 可被多个线程共享(任务复用)。
// Runnable接口是一个函数式接口
Runnable runnable = () -> {
            System.out.println("线程执行: " + Thread.currentThread().getName());
        };
        Thread thread = new Thread(runnable);
        thread.start();

或者:

// 2. 实现 Runnable 接口
class MyRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println("线程执行: " + Thread.currentThread().getName());
    }
}

public class RunnableExample {
    public static void main(String[] args) {
        MyRunnable runnable = new MyRunnable(); // 创建任务对象
        Thread thread = new Thread(runnable);   // 将任务交给 Thread
        thread.start();                         // 启动线程
    }
}

3. 实现 Callable 接口(带返回值)​

​原理​:

  • 通过实现 Callable 接口的 call() 方法定义线程逻辑,可以返回结果或抛出异常。
  • 需配合 FutureTask 或线程池(ExecutorService)使用,FutureTask 实现了 Future 接口,通过它的 get() 方法可以获取 Callable 任务对象的返回值。 Thread 不直接支持 Callable

​特点​:

  • ​支持返回值​​,适合需要获取线程执行结果的场景。
  • ​支持异常处理​​,call() 可以抛出受检异常(Exception)。

局限性:

  • 实现复杂,且get() 方法在等待计算完成时是阻塞的。如果计算被延迟或永久挂起,调用者可能会长时间阻塞。
Callable callable = () -> {
            System.out.println("线程执行: " + Thread.currentThread().getName());
            return 1;
        };
        // 创建 FutureTask,包装 Callable
        FutureTask futureTask = new FutureTask<>(callable);
        // 创建线程并启动
        Thread thread = new Thread(futureTask);
        thread.start();
        // 获取结果:1
        Integer result = futureTask.get();
        System.out.println("线程返回值: " + result);   

4. 使用线程池(ExecutorService)​

​原理​:

  • 通过 Executors 工厂类创建线程池,将 Runnable 或 Callable 任务提交给线程池执行。
  • 线程池复用线程,避免频繁创建/销毁线程的开销。
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ThreadPoolExample {
    // 4. 使用线程池
    public static void main(String[] args) {
        ExecutorService executor = Executors.newFixedThreadPool(2); // 创建固定大小的线程池

        // 提交 Runnable 任务
        executor.submit(() -> {
            System.out.println("Runnable 任务执行: " + Thread.currentThread().getName());
        });

        // 提交 Callable 任务
        executor.submit(() -> {
            System.out.println("Callable 任务执行: " + Thread.currentThread().getName());
            return 100;
        });

        executor.shutdown(); // 关闭线程池(不再接受新任务)
    }

}

 补充:使用​CompletableFuture(异步编程)

总结:

  • 只有 Thread.start() 能创建新线程​​,它是JVM层面启动线程的唯一方式。
  • Runnable.run() 或 Callable.call() 只是任务逻辑的实现,不涉及线程创建。
  • ExecutorService 等高级工具通过封装 Thread.start(),简化了线程管理。
行为​ ​是否创建新线程​ ​执行线程​ ​底层机制​
task.run()/task.call() 当前线程(如main) 普通方法调用
new Thread(task).start() 新线程 JVM创建线程
executor.submit(task) 是(由线程池管理) 线程池中的线程 线程池内部调用 Thread.start()

参考文献:

 大家都说Java有三种创建线程的方式!并发编程中的惊天骗局!

你可能感兴趣的:(JAVA学习笔记,java,开发语言,JUC,并发编程)