直接继承Thread类被劝退,因其破坏类的继承结构且混淆线程调度与业务逻辑;推荐实现Runnable接口解耦任务与执行者,Callable配合Future获取返回值,生产环境应使用带界队列的ThreadPoolExecutor而非Executors工厂方法。

直接继承 Thread 类为什么常被劝退
因为一旦继承了 Thread,这个类就无法再继承其他父类(Java 不支持多继承),实际项目中往往更需要复用已有业务类的层级结构。而且 Thread 类本身职责是“线程调度”,不是“业务逻辑”,把任务代码塞进 run() 里容易混淆关注点。
实操建议:
- 仅在极简 demo 或教学场景下用继承方式,比如
new Thread() { public void run() { System.out.println("hello"); } }.start(); - 重写
run()时别调用start()—— 那会变成普通方法调用,不启动新线程 - 避免在
run()中抛出未捕获异常,否则线程会静默终止,日志里可能只留一句java.lang.ThreadGroup.uncaughtException
实现 Runnable 接口才是主流选择
它解耦了“任务”和“执行者”:你只管定义要做什么(run()),由谁来跑、怎么跑(Thread 或线程池)交给上层决定。这也是 ExecutorService 的底层契约。
常见错误现象:
立即学习“Java免费学习笔记(深入)”;
- 写了
Runnable实现类但忘了传给Thread构造器,比如new MyTask().run()—— 这仍是同步调用 - 误把
Runnable当作线程对象,试图调用start(),编译直接报错:cannot resolve method 'start()'
正确姿势示例:
Runnable task = () -> System.out.println("running in thread: " + Thread.currentThread().getName());
new Thread(task).start(); // 启动新线程
Callable 和 Future 怎么配合获取返回值
Runnable 没有返回值、也不能抛受检异常;而 Callable 允许返回泛型结果、可抛异常,适合需要结果或状态反馈的任务(如异步查数据库、远程调用)。
关键点:
-
Callable的call()方法必须有返回值,类型由泛型指定,比如Callable - 不能直接用
Thread执行Callable,必须通过ExecutorService.submit()得到Future -
Future.get()是阻塞的,超时没返回会一直等,生产环境务必加超时参数,例如future.get(3, TimeUnit.SECONDS)
典型用法:
ExecutorService exec = Executors.newSingleThreadExecutor(); Futurefuture = exec.submit(() -> { Thread.sleep(1000); return "done"; }); String result = future.get(); // 可能抛 InterruptedException / ExecutionException exec.shutdown();
为什么现在更推荐用 Executors 线程池而不是裸 Thread
手动 new Thread() 每次都创建销毁,开销大、难管理、易失控。线程池复用线程、控制并发数、提供队列策略和拒绝策略,是生产环境的事实标准。
注意几个坑:
-
Executors.newFixedThreadPool(10)底层用的是无界队列LinkedBlockingQueue,任务持续堆积会导致 OOM —— 高并发场景应自定义ThreadPoolExecutor并设界队列 -
Executors.newCachedThreadPool()允许无限创建线程,突发流量下可能耗尽系统资源 - 忘记调用
shutdown()或shutdownNow(),JVM 无法正常退出(守护线程除外)
简单安全的起步写法:
ThreadPoolExecutor executor = new ThreadPoolExecutor(
2, 4, 60L, TimeUnit.SECONDS,
new ArrayBlockingQueue<>(100),
new ThreadPoolExecutor.CallerRunsPolicy()
);
executor.execute(() -> doSomething());
线程创建本身很简单,真正复杂的是生命周期管理、异常处理、资源回收和并发协作——这些不会因为用了 lambda 就自动消失。










