Skip to content

进程、线程、协程

进程(Process)

一、是什么?

进程是操作系统分配资源的基本单位,表示一个正在执行的程序实例。每个进程拥有独立的内存空间(代码段、数据段、堆栈等)、文件句柄和系统资源。例如:运行中的Chrome浏览器是一个进程。

二、解决什么问题

解决程序间的隔离性和资源分配问题:

  1. 防止程序间相互干扰(如一个程序崩溃不影响其他程序)
  2. 实现多任务并行(如同时运行IDE和音乐播放器)
  3. 提供安全边界(操作系统级权限控制)

三、核心方法(Java)

  • 创建进程:ProcessBuilder.start()Runtime.exec()
  • 等待进程:Process.waitFor()
  • 销毁进程:Process.destroy()

四、核心状态

  1. 创建(New):进程正在被初始化。
  2. 就绪(Ready):等待CPU调度执行。
  3. 运行(Running):正在CPU上执行。
  4. 阻塞(Blocked):等待I/O等事件(如读取文件)。
  5. 终止(Terminated):执行完毕或被强制结束。

五、应用场景

  • 启动外部程序(如调用系统命令)
  • 需要强隔离的独立应用(如数据库服务)
  • 微服务架构中的服务实例

六、Java示例

java
// 启动记事本进程
ProcessBuilder builder = new ProcessBuilder("notepad.exe");
Process process = builder.start();
process.waitFor();  // 等待进程结束
System.out.println("记事本已关闭");

七、重要注意事项

  1. 进程创建/销毁开销大(需分配独立内存)
  2. 进程间通信(IPC)复杂(需管道、Socket等)
  3. 一个Java程序默认至少一个进程(JVM进程)

线程(Thread)

一、是什么?

线程是CPU调度的最小单位,属于进程内的执行流。一个进程可包含多个线程,共享进程的内存空间(如堆内存),但拥有独立的栈和程序计数器。

二、解决什么问题

解决进程内并发执行效率问题:

  1. 减少上下文切换开销(线程切换比进程快5-10倍)
  2. 共享内存简化通信(无需IPC)
  3. 充分利用多核CPU(并行计算)

三、核心方法(Java)

  • 创建线程:new Thread(Runnable).start()
  • 线程池:Executors.newFixedThreadPool()
  • 同步:synchronizedReentrantLock
  • 协作:wait()/notify()CountDownLatch

四、核心状态(Java线程)

  1. NEW:通过new Thread()创建但未启动。
  2. RUNNABLE:调用start()后,等待或正在运行。
  3. BLOCKED:等待监视器锁(如synchronized)。
  4. WAITING:无期限等待(如object.wait())。
  5. TIMED_WAITING:有限等待(如Thread.sleep(1000))。
  6. TERMINATED:执行完毕。

五、应用场景

  • 高并发服务器(如Tomcat处理请求)
  • 异步任务(如后台日志写入)
  • 实时数据处理(如股票行情分析)

六、Java示例

java
// 多线程下载文件
ExecutorService executor = Executors.newFixedThreadPool(3);
List<Future<String>> results = new ArrayList<>();

for (String url : urls) {
    results.add(executor.submit(() -> {
        return downloadFile(url); // 每个线程下载一个文件
    }));
}

// 获取结果
for (Future<String> future : results) {
    System.out.println(future.get());
}
executor.shutdown();

七、重要注意事项

  1. 需处理线程安全(竞态条件、死锁)
  2. 线程数过多导致上下文切换开销增加
  3. Java线程与OS线程1:1对应(重量级)

协程(Coroutine) - Java虚拟线程(JDK19+)

一、是什么?

协程是用户态轻量级线程,由程序而非OS调度。Java中称为虚拟线程(Virtual Thread),通过Project Loom实现(JDK19+正式发布)。特点:

  • 在用户空间调度(无OS上下文切换)
  • 挂起/恢复由JVM控制
  • 1个OS线程可运行数千个协程

二、解决什么问题

解决传统线程的高并发瓶颈

  1. 消除线程数限制(可创建百万级虚拟线程)
  2. 减少内存占用(初始栈仅4KB vs 线程1MB)
  3. 降低I/O阻塞成本(挂起时不占用OS线程)

三、核心方法(Java)

  • 启动虚拟线程:Thread.startVirtualThread()
  • 虚拟线程池:Executors.newVirtualThreadPerTaskExecutor()
  • 挂起/恢复:自动处理(无需手动)

四、核心状态

协程状态对开发者透明,由JVM管理。本质分为:

  • 运行中:占用载体线程执行。
  • 挂起(Yield):遇到I/O时主动让出CPU(如Files.readString())。
  • 结束:任务完成。

五、应用场景

  • 超高并发服务(10K+连接)
  • I/O密集型任务(如微服务网关)
  • 响应式编程(替代回调地狱)

六、Java示例(JDK21+)

java
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
    IntStream.range(0, 10_000).forEach(i -> {
        executor.submit(() -> {
            Thread.sleep(Duration.ofSeconds(1));
            System.out.println("Task " + i + " on virtual thread");
            return i;
        });
    });
} // 自动关闭executor

七、重要注意事项

  1. CPU密集型任务无优势(仍需要平台线程)
  2. synchronized会阻塞载体线程(优先用ReentrantLock
  3. 调试工具需升级(如支持虚拟线程的调试器)

核心区别

特性进程线程协程(虚拟线程)
隔离性完全隔离(独立内存)共享内存共享内存
创建数量数百个数千个百万级
内存开销高(MB级)中(MB级)极低(KB级)
切换开销高(OS内核切换)中(OS内核切换)低(用户态切换)
调度方操作系统操作系统JVM(用户空间)
通信成本高(IPC)中(需同步)低(无同步需求)
最佳场景强隔离任务CPU密集型任务I/O密集型高并发

总结

  1. 进程:资源隔离的基石,适合独立应用
  2. 线程:并发编程主力,平衡性能与开发成本
  3. 协程(虚拟线程):JDK19+的革命性特性,突破高并发瓶颈
    • 核心价值:用同步代码写异步逻辑,资源利用率提升10倍+
    • 使用建议
      • 新项目优先用虚拟线程(Executors.newVirtualThreadPerTaskExecutor()
      • 替换ThreadPoolExecutor处理I/O任务
      • 避免在虚拟线程中使用synchronized

演进趋势:Java正从"线程池+回调"转向虚拟线程+结构化并发(JDK21)。学习建议:掌握传统线程模型,同时拥抱虚拟线程的轻量化优势。