正文
一、开头先说人话
兄弟们,Java 里说“创建线程”,听起来像一件事,实际上像点烧烤套餐:
- 有的是单点
- 有的是叫老板帮你烤
- 有的是点完还能等结果
- 有的是直接包年办会员
看起来都能“开个线程”,但姿势不一样,后劲也不一样。
一句话先立住:
Java 创建线程,常见有 4 种:继承 Thread、实现 Runnable、实现 Callable 配合 FutureTask、使用线程池。
二、先看总图:4 种方式的关系
三、方式一:继承 Thread
这是最直白的一种,像你自己撸起袖子亲自上烤炉。
public class ThreadDemo extends Thread { @Override public void run() { System.out.println("线程启动了,开始干活"); } public static void main(String[] args) { ThreadDemo thread = new ThreadDemo(); thread.start(); // 别调 run(),那样只是普通方法调用,线程根本没有启动 } }这种方式的特点
- 写法简单,适合入门
- 但 Java 只能单继承
- 继承了 Thread,以后就不方便再继承别的类了
所以它适合练手,不太适合真实项目里到处乱用。
四、方式二:实现 Runnable
这才是更常见的方式。
你可以把它理解成:你不是“员工本身”,你是“任务单”,然后交给线程去执行。
public class RunnableDemo { public static void main(String[] args) { Runnable task = () -> System.out.println("线程启动了,开始执行任务"); Thread thread = new Thread(task); thread.start(); // 任务交给线程,工种分离 } }为什么推荐它?
- 避免单继承限制
- 任务和线程解耦
- 一个任务还可以给多个线程复用
这就像烧烤店里,你写的是“谁去烤 20 串羊肉”这个任务,而不是自己变成烤炉。
Runnable 是一个函数式接口,表示一个可以被线程执行的任务,核心方法是 run()。通过 new Thread(task) 可以把任务交给线程对象,再调用 start() 启动线程。调用 start() 后,JVM 会创建新的线程,并在新线程中执行 Runnable 的 run() 方法。
五、方式三:实现 Callable
前两种方式有个小问题:干完活没法直接返回结果。
如果你想让线程执行完后,顺手把结果带回来,就该上 Callable 了。
import java.util.concurrent.Callable; import java.util.concurrent.FutureTask; public class CallableDemo { public static void main(String[] args) throws Exception { Callable<String> task = () -> { return "线程执行完毕,结果带回来了"; }; FutureTask<String> futureTask = new FutureTask<>(task); new Thread(futureTask).start(); System.out.println(futureTask.get()); // 等线程干完,再拿结果 } }Callable 表示一个有返回值的任务。
FutureTask 表示一个未来可以拿到结果的任务包装器。
它的亮点
- 可以返回结果
- 可以抛异常
- 更适合有“计算结果”的任务
这就像你不是只让伙计去送菜,而是还要求他回来汇报:
“哥,羊肉串送到了,客户还加了两瓶可乐。”
六、方式四:线程池
前面几种方式都像“现招人现上岗”。
小项目凑合,大项目这么玩,线程一多,系统容易被你玩成劳务市场。
这时候就该用线程池了。
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class PoolDemo { public static void main(String[] args) { ExecutorService pool = Executors.newFixedThreadPool(3); pool.execute(() -> System.out.println("线程池里的线程开始干活")); pool.shutdown(); // 活干完可以收工,但别忘了关门 } }线程池像什么?
像店里提前招好 3 个固定员工,来单子就分配,不用每次都重新招人。
它的好处
- 复用线程,减少创建开销
- 方便统一管理
- 更适合真实项目
所以实际开发里,最推荐的是线程池,不是手动一个一个 new Thread()。
七、再来一张图:它们的区别
八、怎么选?
如果你只是想学会怎么起线程:
- 入门看 Thread
- 日常写法用 Runnable
- 需要返回值用 Callable
- 真上项目优先线程池
你可以这么记:
Thread 是入门版,Runnable 是常规版,Callable 是带结果版,线程池是生产环境版。
九、一句话总结
Java 创建线程有很多方式,但真正项目里最常用、最靠谱的,通常还是线程池。