☕ 第十二章 多线程
📝 一句话概括

进程是工厂(独立占资源),线程是工厂里的工人(共享资源、真正干活)——Java 程序一启动就有一条 main 主线程在跑,之前的所有代码都是它从头干到尾的。多线程 = 请更多工人同时干活。

上一章收官时欠了一笔账:11.4 说连接不能存成员变量全局共用——为什么共用会出事?答案藏在这章:多个工人抢同一张桌子会打架。先从概念打地基。

一、进程:正在运行的程序

程序躺在硬盘上是「尸体」,双击运行、被加载进内存才开始「活」——这个活着的程序就是进程。

收一笔老账:1.4 运行机制 讲过程序要加载进内存才执行,10.1 讲过内存是临时工位——现在补上最后一块拼图:加载进内存后,那个「正在跑的东西」的正式名字就叫进程。

二、线程:进程里真正干活的

进程只是个「厂牌」,真正干活的是厂里的工人——线程。

💡 为什么软件都要多线程

单线程的软件「一次只能干一件事」:下载没完成界面就卡死点不动。多线程把「下载」这类慢活分给别的工人,主工人继续陪用户聊天——界面不卡、体验流畅,就是多线程存在的理由。

三、并发与并行:两个「同时」不是一个「同时」

并发 Concurrency 并行 Parallelism
本质 交替执行,快速切换 同时执行,互不耽误
比喻 单车道轮流放行 多车道并排开
硬件条件 单核就能做(切换够快就行) 要靠 CPU 多核(几核真并行几路)
口诀 宏观同时,微观轮流 物理意义上的同时

一个常见误解顺带澄清:电脑「同时」跑着几十个程序,多数时候是并发——CPU 在进程线程之间飞快切换,快到你以为它们是同时的;只有多核 CPU 才有真正的并行。

📝 抢占式调度

哪个线程什么时候抢到 CPU 跑、跑多久才被换下来——完全随机,程序员控制不了(只能干预优先级,不能指定时刻)。这个「随机」特性后面调试多线程程序时会天天体会到:同一段代码每次跑,输出顺序可能都不一样。

四、main 主线程:你一直在用的那条线程

Java 程序一启动,JVM 至少创建一条线程执行 main 方法——这条线程就叫主线程。之前十一个章节写的全部代码,都是在主线程里从第一行跑到最后一行的:

public class Demo16 {
    public static void main(String[] args) {
        // 打印当前正在执行这行代码的线程名字
        System.out.println(Thread.currentThread().getName());
    }
}

输出:

main

Thread.currentThread() 拿到「当前正在执行这行代码的线程」,它的名字就叫 main——铁证:main 方法本身就是被一条叫 main 的线程在执行。

🧪 三个 30 秒小实验

实验 1:任务管理器看进程 Ctrl+Shift+Esc → 进程标签 → 找到 IDEA / 爱奇艺 → 右键「转到详细信息」能看到对应的底层进程条目——进程天天在你眼前,只是以前没点开看。

实验 2:给 main 里加个死循环 while(true){} 卡住 main → 控制台永远跑不完 → 程序没有结束。这就是主线程:它不退出,进程就一直活着。

实验 3:JVM 除了 main 还有别的线程吗? 打印 Thread.currentThread().getName() 只看到 main,但其实 JVM 自己还养着 GC(垃圾回收)等幕后线程——工人不止一个,只是大多数不归你管。

五、常见误区

  1. 进程 = 程序——程序是硬盘上的文件(尸体),进程是运行中的程序(活体)
  2. 进程在干活——进程只是容器,干活的是里面的线程
  3. 多线程一定更快——单核 CPU 上多任务只是并发切换,切换本身还有开销;多线程提速看场景(IO 等待时让出 CPU 才是真正的提速点,后文细说)
  4. 并发和并行随便叫——交替执行叫并发,多核同时执行叫并行,面试常考
  5. main 方法特殊——它不特殊,只是被主线程执行的普通方法;主线程结束 main 就结束,但别的线程还可以继续跑(这章后面就能亲眼看到)

六、自测题

❓ Q1:进程和线程的区别,一句话?

进程是正在运行的程序、有独立内存空间;线程是进程内部的执行单位、共享进程资源。工厂和工人的关系。

❓ Q2:并发和并行的核心区别?

并发 = 交替执行、宏观同时微观轮流(单核可做);并行 = 多核真正同时执行。

❓ Q3:为什么说「你早就用过主线程了」?

Java 程序启动时 JVM 自动创建 main 主线程执行 main 方法,之前所有代码都是它跑的。Thread.currentThread().getName() 打印出来就是 main。

❓ Q4:单核 CPU 能并行吗?

不能。单核只能并发(快速交替);真正的并行需要多核,几核真并行几路。

❓ Q5(毕业题):用「工厂与工人」解释 11.4 那笔账——为什么数据库连接不能存成员变量让所有代码共用?

连接好比工厂里一张工作台(共享资源)。只来一个工人时随便用;多个工人(多线程)同时挤一张工作台就会互相踩——A 刚把材料摆好,B 一把抢走全打乱。所以要么一人一台(每次 getConnection 租新连接),要么排队用(加锁)——这正是本章后面「线程安全」要收的账。能把共享资源 + 多人同时操作两点说出来就算毕业。

下一步学什么

相关笔记