首页 / Java 入门教程 / 进程与线程

Java 入门教程

进程与线程

本教程共 100 篇 · 第 93 篇 · 更新于 2026-08-05 · 约 6 分钟阅读

JavaJava 入门教程进程线程并发多线程

93. 进程与线程

本节目标:分清进程和线程的区别,理解并发与并行,知道多线程能带来什么、又要付出什么代价。

从任务管理器说起

打开 Windows 任务管理器,你会看到一列正在运行的程序:浏览器、编辑器、音乐播放器。

每一个运行中的程序,就是一个进程

进程是操作系统分配资源的基本单位。系统给每个进程划一块独立的内存空间,进程 A 改不了进程 B 的数据,这就是所谓的「隔离」。一个程序崩了不会拖垮其他程序,靠的就是这层隔离。

再往下看,任务管理器里每个进程还能展开,显示它包含多少个线程。

线程是进程内部的执行单元

线程是进程里的一条执行路径,是 CPU 调度的基本单位。

一个进程至少有一个线程,也可以有很多个。同一个进程内的所有线程共享这个进程的内存空间——同一份变量,谁都能读,谁都能写。

拿餐厅打比方:整个餐厅是一个进程,占着一个铺面、一套厨具、一批食材;服务员就是线程,他们共用这些资源,各自负责不同的桌子。

再开一家分店就是新起一个进程,铺面和食材完全独立。多招几个服务员就是新起线程,成本低得多,但会抢厨具。

两者的关键差异

对比项进程线程
定义资源分配的单位调度执行的单位
内存相互独立共享所属进程的内存
创建开销
切换开销
通信方式管道、Socket、共享内存等直接读写共享变量
相互影响一个崩了不影响别的一个崩了可能拖垮整个进程

最后一行值得画重点。线程共享内存带来了效率,也带来了风险——某个线程把共享数据搞乱了,整个进程都得跟着遭殃。

并发不等于并行

这两个词经常被混用,但含义不同。

并发是指多个任务在同一时间段内都在推进。并行是指多个任务在同一时刻真正同时执行。

单核 CPU 上只有并发,没有并行。操作系统把 CPU 时间切成极小的片段,轮流分给各个线程,切换速度快到人察觉不出来,看起来像是同时在跑。

多核 CPU 才有真正的并行。4 个核心可以同时执行 4 个线程,互不占用对方的时间。

Note

现在的电脑基本都是多核,所以「并发」和「并行」经常同时发生。写代码时不用刻意区分,但要明白:线程数超过核心数之后,多出来的线程只能靠时间片轮转,不会带来额外的计算能力。

线程共享什么、独占什么

理解并发问题的前提,是搞清楚内存怎么划分。

共享的部分

  • 堆:所有对象实例都在这里,任何线程都能访问
  • 方法区:类信息、静态变量、常量池

独占的部分

  • 虚拟机栈:方法调用的栈帧,局部变量放在这里
  • 程序计数器:记录当前线程执行到哪一行字节码

这个划分直接决定了什么代码有线程安全问题。

局部变量在栈上,每个线程一份,天然安全。成员变量和静态变量在堆和方法区,被共享,多线程同时改就可能出错。

Tip

记住一句话:只操作局部变量的方法一定是线程安全的。这是判断线程安全最快的一招。

用代码看一眼

Java 程序启动时,JVM 会自动创建一个 main 线程来执行 main 方法。但它不是唯一的线程:

public class ThreadInfo {
    public static void main(String[] args) {
        Thread current = Thread.currentThread();
        System.out.println("当前线程名:" + current.getName());
        System.out.println("线程 ID:" + current.threadId());
        System.out.println("是否守护线程:" + current.isDaemon());

        System.out.println("可用处理器核数:" +
                Runtime.getRuntime().availableProcessors());
        System.out.println("当前活动线程数:" + Thread.activeCount());
    }
}
```text

输出类似:

```text
当前线程名:main
线程 ID:1
是否守护线程:false
可用处理器核数:8
当前活动线程数:1

Thread.activeCount() 只统计当前线程组的线程。实际上后台还跑着垃圾回收、JIT 编译等线程,它们由 JVM 管理,业务代码看不到。

threadId() 是 Java 19 引入的方法,替代了旧的 getId()

多线程能带来什么

提升响应速度。桌面程序把耗时任务丢给后台线程,界面线程继续响应点击,用户不会看到卡死的窗口。

提高吞吐量。一个 Web 服务器同时处理上千个请求,每个请求一个线程(或者交给线程池),总处理量远超单线程。

充分利用多核。一份大数据切成 8 份交给 8 个线程算,理论上能快 8 倍。单线程再怎么优化也只能用一个核。

掩盖 I/O 等待。读磁盘、等网络响应时 CPU 是闲着的。此时切到别的线程干活,整体效率就上去了。

代价也不小

多线程不是免费的午餐。

线程安全问题。多个线程改同一份数据,结果可能不符合预期。这类 bug 往往偶发,测试环境跑一万次都正常,上线就出问题,排查困难。

上下文切换开销。CPU 从一个线程切到另一个线程,要保存和恢复寄存器、刷新缓存。线程开太多,CPU 大部分时间都花在切换上,实际干活反而少了。

内存占用。每个线程默认要分配 1MB 左右的栈空间。开一千个线程就是 1GB,很容易撑爆内存。

死锁风险。两个线程互相等对方释放锁,谁也动不了,程序永久卡住。

Warning

不要因为「多线程快」就到处开线程。先确认瓶颈真的在 CPU 或 I/O 等待上,再考虑并发。很多时候优化算法带来的提升,比堆线程大得多。

多进程还是多线程

两种方案都能实现并发,取舍看场景。

需要强隔离、单个任务崩溃不能影响全局,选多进程。浏览器给每个标签页开独立进程就是这个道理,一个页面崩了不至于整个浏览器关掉。

需要频繁共享数据、创建销毁频繁,选多线程。开销小,通信直接读写内存即可。

Java 的定位很明确:主推多线程。语言层面内置了 Threadsynchronizedjava.util.concurrent 一整套工具,多进程反而要借助 ProcessBuilder 调用外部命令,不那么顺手。

本节小结

  • 进程是资源分配单位,内存相互隔离;线程是调度单位,共享进程内存。
  • 并发是交替推进,并行是同时执行,单核只有并发。
  • 堆和方法区共享,栈和程序计数器线程独占。
  • 只用局部变量的方法天然线程安全。
  • main 线程由 JVM 自动创建,后台还有 GC 等系统线程。
  • 多线程提升响应和吞吐,代价是线程安全、切换开销、内存占用和死锁风险。
  • Java 的并发模型以多线程为主。