选线程创建方式需按任务需求决定:无返回值且一次性用Thread或匿名类;需复用或解耦用Runnable;要结果或异常处理用Callable+Future;高频长期任务必须自定义ThreadPoolExecutor。

选线程创建方式,关键不是背“有几种”,而是看任务要什么:要不要返回值、能不能复用、并发量多大、是否长期运行。不同场景对应不同方案,用错容易引发资源泄漏、OOM 或逻辑阻塞。
简单一次性任务,比如日志记录、异步通知
适合用 继承 Thread 类 或 匿名内部类,代码短、上手快。
- 任务逻辑极简(如打印一句日志、发一条短信),不需结果,也不需要复用;
- 调用频次低(一天几次)、生命周期短(执行完就结束);
- 注意:不能直接调用 run(),必须用 start();也不能在已有继承体系的类里再继承 Thread。
多线程执行相同逻辑,或需复用任务代码
首选 实现 Runnable 接口,这是生产中最常用的方式。
- 同一个 Runnable 实例可传给多个 Thread,实现任务与线程解耦;
- 避免单继承限制——你的业务类可以同时继承 Service 类、实现 Runnable,不影响扩展;
- 配合 Lambda 更简洁:
new Thread(() -> System.out.println("Hello")).start();
需要获取执行结果或处理异常
必须用 Callable + FutureTask / ExecutorService。
立即学习“Java免费学习笔记(深入)”;
- Runnable 的 run() 无法返回值、也不能抛检查异常;Callable 的 call() 可返回泛型结果、可抛 Exception;
- 典型场景:批量查数据库后汇总、异步计算折扣金额、远程接口调用并等待响应;
- 搭配线程池使用更稳妥,避免手动管理线程生命周期。
高频、大量、长期运行的任务
一律走 自定义 ThreadPoolExecutor,别碰 Executors 工具类的快捷方法。
- FixedThreadPool 队列无界,突发流量易 OOM;CachedThreadPool 线程数无上限,可能耗尽 CPU 或内存;
- 根据业务压测数据设 corePoolSize(CPU 密集型 ≈ 核心数,IO 密集型可适当放大)、maxPoolSize、队列类型(SynchronousQueue / LinkedBlockingQueue / ArrayBlockingQueue);
- 务必配置拒绝策略(如 CallerRunsPolicy 避免丢任务,或自定义日志+告警)。


















