Skip to content

线程创建方式

四种方式,适用场景各不同。

方式总览

方式实现返回值异常处理推荐场景
继承 Threadextends Threadvoid不能抛受检异常简单场景(不推荐)
实现 Runnableimplements Runnablevoid不能抛受检异常通用场景
实现 Callableimplements CallableV可以抛受检异常需要返回值的场景
线程池Executors/ThreadPoolExecutorFuture/Void按需处理生产环境(强烈推荐)

方式一:继承 Thread

最直接的方式,但不推荐

java
class MyThread extends Thread {
    @Override
    public void run() {
        System.out.println("线程执行中: " + Thread.currentThread().getName());
    }
}

// 使用
MyThread thread = new MyThread();
thread.start();  // 记住是 start(),不是 run()

为什么说不推荐?

java
// 问题一:Java 单继承限制
class MyClass extends Parent { }  // 只能继承一个类
// 如果用 Thread,就没法再继承其他类了

// 问题二:任务和线程耦合
// MyThread 既包含任务逻辑,又包含线程管理
// 不能把同一个任务交给多个线程执行

start() vs run()

java
Thread thread = new Thread(() -> System.out.println("线程运行"));

thread.start();  // ✅ 启动新线程,异步执行
thread.run();    // ❌ 只是普通方法调用,同步执行

方式二:实现 Runnable

推荐的基本方式

java
class MyRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println("线程执行中: " + Thread.currentThread().getName());
    }
}

// 使用
Thread thread = new Thread(new MyRunnable());
thread.start();

优点

  • 解决单继承问题
  • 任务和线程解耦
  • 可以共享同一个 Runnable 实例
java
// 同一个任务,多个线程执行
class ShareTask implements Runnable {
    private int count = 0;

    @Override
    public void run() {
        count++;
        System.out.println(Thread.currentThread().getName() + " - count: " + count);
    }
}

ShareTask task = new ShareTask();
new Thread(task, "A").start();  // A - count: 1
new Thread(task, "B").start();  // B - count: 2
new Thread(task, "C").start();  // C - count: 3

Lambda 简化(JDK 8+)

java
// 完整写法
Thread thread1 = new Thread(new Runnable() {
    @Override
    public void run() {
        System.out.println("Hello");
    }
});

// Lambda 简化(JDK 8+)
Thread thread2 = new Thread(() -> System.out.println("Hello"));

方式三:实现 Callable

Runnable 的问题是不能返回结果,Callable 解决了这个问题:

java
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;

class MyCallable implements Callable<Integer> {
    @Override
    public Integer call() throws Exception {
        int sum = 0;
        for (int i = 1; i <= 100; i++) {
            sum += i;
        }
        return sum;  // 可以返回结果
    }
}

// 使用
MyCallable callable = new MyCallable();
FutureTask<Integer> future = new FutureTask<>(callable);
Thread thread = new Thread(future);
thread.start();

// 获取结果(会阻塞直到结果返回)
try {
    Integer result = future.get();  // 5050
    System.out.println("计算结果: " + result);
} catch (Exception e) {
    e.printStackTrace();
}

Callable vs Runnable

对比项RunnableCallable
返回值voidV
异常不能抛出受检异常可以抛出受检异常
使用方式Thread / ExecutorService.execute()ExecutorService.submit()
配套类FutureTask

FutureTask 的额外能力

java
FutureTask<Integer> future = new FutureTask<>(() -> {
    // 模拟耗时操作
    Thread.sleep(2000);
    return 42;
});

new Thread(future).start();

System.out.println("任务是否完成: " + future.isDone());

// 带超时的获取
Integer result = future.get(5, TimeUnit.SECONDS);  // 等 5 秒
System.out.println("结果: " + result);

// 取消任务
future.cancel(true);  // true = 可以中断正在执行的任务

方式四:线程池(生产环境推荐)

线程创建和销毁有开销,线程池复用线程,避免频繁创建销毁:

java
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

// 常见线程池类型
ExecutorService cachedPool = Executors.newCachedThreadPool();    // 动态线程数
ExecutorService singlePool = Executors.newSingleThreadExecutor(); // 单线程
ExecutorService fixedPool = Executors.newFixedThreadPool(5);     // 固定线程数

// 提交任务
fixedPool.submit(() -> System.out.println("任务1"));
fixedPool.submit(() -> System.out.println("任务2"));
fixedPool.submit(() -> System.out.println("任务3"));

// 关闭线程池
fixedPool.shutdown();      // 不再接受新任务,等待已提交任务完成
fixedPool.shutdownNow();   // 尝试停止所有任务

// 带返回值的提交
Future<Integer> future = fixedPool.submit(() -> {
    Thread.sleep(1000);
    return 42;
});
Integer result = future.get();  // 阻塞等待结果

为什么不推荐 Executors 工厂方法?

java
// 问题:Executors 创建的线程池可能有风险
// FixedThreadPool 和 SingleThreadExecutor 使用无界队列,可能 OOM
ExecutorService executor = Executors.newFixedThreadPool(2);
// 任务太多,队列无限增长,内存爆炸

// 推荐:手动创建线程池,明确参数
ThreadPoolExecutor executor = new ThreadPoolExecutor(
    2,                      // 核心线程数
    4,                      // 最大线程数
    60L,                    // 空闲线程存活时间
    TimeUnit.SECONDS,       // 时间单位
    new ArrayBlockingQueue<>(10),  // 有界队列,防止 OOM
    new ThreadPoolExecutor.AbortPolicy()  // 拒绝策略
);

对比总结

简单场景

java
// 临时任务,不复用,直接用 Lambda
Thread t = new Thread(() -> {
    System.out.println("一次性任务");
});
t.start();

需要结果

java
// 用线程池 + Callable
ExecutorService executor = Executors.newFixedThreadPool(4);
Future<Integer> future = executor.submit(() -> {
    return calculateSum();
});
Integer result = future.get();

生产环境

java
// 自定义线程池,参数可控
ThreadPoolExecutor executor = new ThreadPoolExecutor(
    Runtime.getRuntime().availableProcessors(),  // CPU 核心数
    Runtime.getRuntime().availableProcessors() * 2,  // 最大线程数
    60L, TimeUnit.SECONDS,
    new LinkedBlockingQueue<>(1000),
    new ThreadPoolExecutor.CallerRunsPolicy()
);

Java 21+ 虚拟线程

java
// 大量 I/O 任务,用虚拟线程
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
    IntStream.range(0, 10_000).forEach(i ->
        executor.submit(() -> {
            // 模拟 I/O
            Thread.sleep(Duration.ofSeconds(1));
        })
    );
}

Thread 类常用方法

java
Thread thread = new Thread(() -> {
    System.out.println("执行中");
}, "MyThread");

// 设置
thread.setName("MyThread");
thread.setPriority(Thread.MAX_PRIORITY);  // 1-10
thread.setDaemon(true);  // 守护线程

// 获取
thread.getId();           // 线程 ID
thread.getName();         // 线程名称
thread.getPriority();     // 优先级
thread.getState();        // 线程状态
thread.isAlive();         // 是否存活
thread.isDaemon();        // 是否守护线程
thread.isInterrupted();   // 是否被中断

// 控制
thread.start();           // 启动
thread.join();            // 等待结束
thread.join(1000);        // 等待超时(1秒)
thread.sleep(1000);       // 休眠(不释放锁)
thread.interrupt();       // 中断
Thread.yield();          // 礼让(建议调度器切换)

总结

  1. 简单临时任务:直接 new Thread(() -> {...})
  2. 通用场景:用 Runnable + 线程池
  3. 需要返回值:用 Callable + Future + 线程池
  4. 生产环境:自定义 ThreadPoolExecutor
  5. 大量 I/O 任务:用虚拟线程(Java 21+)

记住start() 启动线程,run() 只是普通方法调用。

基于 VitePress 构建