应避免直接继承Thread类实例化,而应分离任务与执行者:优先使用Runnable/Callable配合线程池,需返回值时用Future,复杂编排用CompletableFuture。

直接实例化 Thread(即继承 Thread 类并 new MyThread().start())在实际开发中应尽量避免。这不是语法错误,而是设计隐患——它容易导致耦合加重、复用困难、线程资源失控,且与现代 Java 并发模型脱节。
核心原则:把“任务”和“执行者”分开。Thread 是执行载体,不是业务逻辑容器;真正该定义的是“要做什么”,而不是“谁来跑”。
用 Runnable 接口替代继承 Thread
这是最基础也最常用的解法。Runnable 是一个函数式接口,只定义 run() 方法,天然适合描述任务逻辑。
- ✅ 支持 lambda 表达式,写法简洁
- ✅ 可被任意类实现,不破坏原有继承结构
- ✅ 能无缝接入线程池、定时器、CompletableFuture 等高级并发工具
// 好:任务独立,可复用
Runnable task = () -> {
System.out.println("执行后台任务");
// 模拟耗时操作
};
// 启动方式1:临时起线程(不推荐高频使用)
new Thread(task).start();
// 启动方式2:交给线程池(推荐)
ExecutorService pool = Executors.newFixedThreadPool(4);
pool.submit(task); // 无返回值⚠️ 注意:
new Thread(task).start()虽比继承Thread类稍好,但仍属“临时线程”,应仅用于极简场景(如 GUI 初始化、单次异步日志)。生产环境优先走线程池。立即学习“Java免费学习笔记(深入)”;
用线程池统一管理线程生命周期
每次 new Thread() 都会创建 OS 级线程,开销大、不可控、易 OOM。线程池通过复用 Thread 实例,解决资源浪费和调度混乱问题。
- ✅ 控制最大并发数,防系统过载
- ✅ 支持队列缓冲、拒绝策略、优雅关闭
- ✅ 所有标准线程池(
ThreadPoolExecutor、ForkJoinPool)只接收Runnable或Callable
// 推荐:使用自定义线程池(避免 Executors 的陷阱)
ThreadPoolExecutor executor = new ThreadPoolExecutor(
2, // 核心线程数
10, // 最大线程数
60L, // 空闲线程存活时间
TimeUnit.SECONDS,
new LinkedBlockingQueue<>(100), // 任务队列
new ThreadFactoryBuilder().setNameFormat("biz-task-%d").build(),
new ThreadPoolExecutor.CallerRunsPolicy() // 拒绝策略
);
executor.submit(() -> doSomething());? 小技巧:Spring 项目中可通过
@Async+TaskExecutor注解间接使用线程池,无需手动 new。
有返回值或异常处理时,用 Callable + Future
当任务需要结果或可能抛异常,Runnable 不够用。此时用 Callable(支持泛型返回值、可抛检查异常),配合 Future 获取执行结果。
Callable<String> task = () -> {
Thread.sleep(1000);
return "任务完成";
};
Future<String> future = executor.submit(task);
String result = future.get(); // 阻塞获取结果- ✅
Callable.call()可返回值、可抛异常,语义更完整 - ✅
Future提供超时、取消、状态查询能力 - ✅ 同样兼容线程池,不依赖
Thread实例化
特殊场景:用 CompletableFuture 做异步编排
如果任务之间有依赖(比如 A 完成后触发 B),或需要组合多个异步结果,CompletableFuture 是更现代的选择:
CompletableFuture.supplyAsync(() -> fetchFromDB(), executor)
.thenApply(data -> transform(data))
.thenAccept(result -> saveToCache(result))
.exceptionally(ex -> {
log.error("异步链路失败", ex);
return null;
});- ✅ 不暴露
Thread或Runnable底层细节 - ✅ 支持非阻塞回调、链式编排、异常传播
- ✅ 默认使用
ForkJoinPool.commonPool(),也可指定自定义线程池
不复杂但容易忽略


















