进程、线程、协程是java开发中极为重要的要素,其中,进程是操作系统资源分配和调度的基本单位,每个进程都有独立的内存空间(代码段、数据段、堆栈等)。进程间通信需要通过特定的IPC机制(如管道、消息队列、共享内存等)。其特点如下:
(1)独立性:一个进程崩溃不会影响其他进程
(2)资源开销大:创建和销毁进程需要较大系统开销
(3)通信复杂:进程间通信需要特殊机制
(4)并发性:多个进程可以并发执行(单核CPU通过时间片轮转实现)
一个进程通常包含5个部分:
(1)代码段:存储可执行指令,通常是只读的
(2)数据段 : 存储全局变量和静态变量
(3)堆:动态分配的内存区域
(4) 栈:存储局部变量、函数调用信息等
(5) 进程控制块:操作系统维护的进程元数据(进程状态、寄存器值、PID等)
其生命周期包含创建,就绪,运行,阻塞,终止5个周期:
而线程则是CPU调度的基本单位,属于同一进程的多个线程共享进程的内存空间。线程比进程更轻量级,创建和切换开销更小。其主要特点如下:
(1)共享内存:同一进程的线程共享堆内存,但有自己的栈
(2)开销较小:创建和切换比进程快
(3)需要同步:共享数据需要同步机制保证线程安全
(4)并发执行:在多核CPU上可以真正并行运行
相较于进程,线程的生命周期更多,分为:
新建:线程被创建但尚未启动
可运行:线程正在JVM中执行或等待CPU时间片
阻塞:线程等待监视器锁(synchronized)
等待:线程无限期等待其他线程执行特定操作
定时等待:线程在指定时间内等待
终止:线程已执行完毕
最后是协程,协程是用户态的轻量级线程,由程序员在用户空间控制调度,不依赖操作系统内核。Java通过Project Loom的虚拟线程支持协程。其主要特点如下:
(1)极轻量级:创建百万级协程不是问题
(2)无阻塞:协程切换由程序控制,不涉及内核态切换
(3)高并发:适合IO密集型任务
(4)同步编码,异步执行:用看似同步的代码实现异步操作
import java.io.BufferedReader;
import java.io.InputStreamReader;
//进程演示
public class ProcessDemo {
public static void main(String[] args) {
try {
// 创建一个 ProcessBuilder 对象,用于启动外部进程
ProcessBuilder processBuilder = new ProcessBuilder("ping", "www.baidu.com");
// 启动进程并返回 Process 对象
Process process = processBuilder.start();
// 获取进程的输入流,用于读取进程输出的信息
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
// 逐行读取进程输出并打印到控制台
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line); // 打印输出
}
// 等待进程执行完毕,并返回进程的退出码
int exitCode = process.waitFor();
System.out.println("进程退出码:" + exitCode); // 打印退出码
} catch (Exception e) {
// 捕获并处理可能的异常
e.printStackTrace();
}
}
}
// 线程演示案例
public class ThreadDemo {
public static void main(String[] args) {
// 创建一个 Runnable 接口的匿名实现
Runnable task = new Runnable() {
@Override
public void run() {
// 线程执行的任务
for (int i = 0; i < 5; i++) {
System.out.println("线程执行中,i = " + i);
try {
// 使当前线程休眠 1 秒钟
Thread.sleep(1000);
} catch (InterruptedException e) {
// 捕获异常,输出错误信息
e.printStackTrace();
}
}
}
};
// 创建一个 Thread 对象并传入 Runnable 任务
Thread thread = new Thread(task);
// 启动线程
thread.start();
// 主线程也可以执行一些任务
for (int i = 0; i < 5; i++) {
System.out.println("主线程执行中,i = " + i);
try {
// 主线程休眠 1 秒钟
Thread.sleep(1000);
} catch (InterruptedException e) {
// 捕获异常,输出错误信息
e.printStackTrace();
}
}
}
}
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
//协程演示案例
public class CoroutineDemo {
public static void main(String[] args) {
// 模拟协程执行的任务1
CompletableFuture<Void> task1 = CompletableFuture.runAsync(() -> {
try {
System.out.println("协程任务1开始执行...");
Thread.sleep(1000); // 模拟任务耗时1秒
System.out.println("协程任务1执行完成");
} catch (InterruptedException e) {
e.printStackTrace();
}
});
// 模拟协程执行的任务2
CompletableFuture<Void> task2 = CompletableFuture.runAsync(() -> {
try {
System.out.println("协程任务2开始执行...");
Thread.sleep(500); // 模拟任务耗时0.5秒
System.out.println("协程任务2执行完成");
} catch (InterruptedException e) {
e.printStackTrace();
}
});
// 使用 `join()` 方法等待任务完成,类似于协程的等待机制
task1.join();
task2.join();
System.out.println("所有协程任务完成");
}
}