进程和线程就像 “公司” 和 “员工” 的关系:
- 进程是独立运行的“公司”,有自己独立的办公室(内存)、财务(资源)和业务。
- 线程是公司里的“员工”,共享办公室和资源,各自处理不同的任务,协作完成公司目标。
一、核心区别对比
| 对比项 | 进程 | 线程 |
|---|---|---|
| 资源占用 | 独立内存空间,资源开销大 | 共享进程内存,资源开销小 |
| 独立性 | 互相隔离,一个进程崩溃不影响其他进程 | 共享进程资源,一个线程崩溃可能导致整个进程挂掉 |
| 创建开销 | 大(需分配独立资源) | 小(复用进程资源) |
| 通信方式 | 复杂(管道、Socket、文件等) | 简单(直接读写共享内存) |
| Java中的实现 | 通过Process类启动外部程序 | 通过Thread类或线程池创建 |
二、举个现实例子
-
进程:
- 你同时打开了微信和Chrome浏览器 → 这是两个独立的进程。
- 微信崩溃了,Chrome还能继续用(互不影响)。
-
线程:
- 在Chrome里打开多个标签页 → 每个标签页可能对应一个线程。
- 如果某个标签页的线程卡死(比如脚本死循环),整个Chrome可能卡住。
三、Java中的具体实现
1. 进程
-
创建方式:通过
ProcessBuilder或Runtime.exec()启动外部程序。 -
特点:
- 完全独立,无法直接访问其他进程的内存。
- 适合调用外部工具(如执行Shell脚本)。
代码示例:
// 启动一个外部进程(比如打开记事本)
Process process = new ProcessBuilder("notepad.exe").start();
2. 线程
-
创建方式:
- 继承
Thread类,重写run()方法。 - 实现
Runnable接口,传给Thread对象。 - 使用线程池(如
ExecutorService)。
- 继承
代码示例:
// 方式1:继承Thread
class MyThread extends Thread {
@Override
public void run() {
System.out.println("线程运行中");
}
}
new MyThread().start();
// 方式2:实现Runnable
new Thread(() -> System.out.println("线程运行中")).start();
四、为什么用多线程?
- 资源共享:线程直接共享进程的内存(如全局变量),通信方便。
- 轻量高效:创建和切换线程比进程快得多。
- 并行处理:利用多核CPU,同时处理多个任务(如同时下载多个文件)。
五、为什么用多进程?
- 安全性:进程间隔离,一个崩溃不影响其他进程。
- 稳定性:适合运行独立的外部程序(如调用Python脚本)。
- 资源独占:某些场景需要独立资源(如独立JVM实例)。
六、如何选择?
| 场景 | 选进程 | 选线程 |
|---|---|---|
| 需要隔离性和稳定性 | ✅(如银行系统不同服务) | ❌ |
| 高并发且资源共享 | ❌ | ✅(如Web服务器处理请求) |
| 调用外部程序 | ✅(如执行系统命令) | ❌ |
七、总结
- 进程:独立王国,安全但笨重 → 适合隔离任务或调用外部程序。
- 线程:团队协作,高效但需谨慎 → 适合高并发和资源共享。
口诀:
「进程像公司,独立又隔离
线程如员工,协作效率高
共享资源用线程,安全独立选进程!」