钩子:你的程序是条独木桥
回想第 3 篇:Java 代码从 main 方法开始,一行行往下执行。下载没下完,后面全部干等——一步卡,步步卡。
真实的软件不是这样的:微信能一边收消息一边传文件,浏览器一边加载网页一边播视频。秘密就是——它们不止一条执行流水线。
线程 = 一条独立的执行流水线。 一个进程至少有一条线程(跑 main 的那条),开多条线程,就能一心多用。
顺便颠覆一下:你现在写了几十篇的 main 方法,它自己也是个线程,名字就叫 main。
核心:两种姿势开线程
// 姿势 A:继承 Thread(简单直观,但占用了唯一的继承名额)
Thread download = new Thread() {
@Override
public void run() {
System.out.println("下载中…当前线程:" + Thread.currentThread().getName());
}
};
// 姿势 B:实现 Runnable(推荐——不占继承名额,还能配合线程池复用)
Thread ui = new Thread(() -> {
System.out.println("渲染界面…当前线程:" + Thread.currentThread().getName());
});
关键一步:让线程跑起来,必须调 start(),不是 run():
download.start(); // ✅ 向 JVM 申请新线程,由新线程执行 run()
download.run(); // ❌ 只是普通方法调用,还在 main 线程里跑
这个坑 90% 的新手都踩过:调 run() 时一切"正常",就是没有并发效果——因为根本没有新线程,还是 main 在串行执行。

实验:亲眼看"同时"
我跑了一组真实实验(demo 里有完整代码):
串行:下载 600ms + 渲染 300ms = 922ms
并行:两个线程同时干 = 608ms(约等于最长那一段)
再让两个线程交替说话,你会看到输出顺序每次运行都可能不同——谁抢到 CPU 谁先说,这是线程调度的随机性。记住这个"随机",下一篇的大坑就藏在这里。
常用三招
| 方法 | 作用 | 一句话记忆 |
|---|---|---|
start() |
真正开新线程 | start 才有线程,run 只是方法 |
sleep(ms) |
当前线程睡一会儿 | 让出 CPU,模拟耗时 |
join() |
等某个线程干完再走 | main 在此"堵车"等它 |
坑点回顾 + 下篇引线
多线程很好用,但有个致命问题没解决:多个线程改同一个变量会出事。
还记得第 8 篇的 i = i++ 吗?那只是单线程里的坑。下一篇,两个线程同时对同一个 i 做 i++,结果会让人怀疑人生——这是并发编程的第一课"线程安全",也是整个模块六的核心悬念。
速查表
| 要点 | 内容 |
|---|---|
| 线程是什么 | 一条独立的执行流水线,main 也是线程 |
| 开线程姿势 | 继承 Thread / 实现 Runnable(推荐) |
| 启动 | start(),不是 run() |
| 让路 | sleep(ms) |
| 等待 | join() |
| 隐患 | 多线程共改一个变量 → 线程安全问题(下篇) |
本文示例代码均已本地实测通过,可直接运行。
对应文件:ThreadDemo.java
橙码酱,分享更有用的技术知识,助你成为更优秀的开发者。