Java学习 -------进程、线程、协程
进程、线程、协程是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() {@Overridepublic 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) {// 模拟协程执行的任务1CompletableFuture<Void> task1 = CompletableFuture.runAsync(() -> {try {System.out.println("协程任务1开始执行...");Thread.sleep(1000); // 模拟任务耗时1秒System.out.println("协程任务1执行完成");} catch (InterruptedException e) {e.printStackTrace();}});// 模拟协程执行的任务2CompletableFuture<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("所有协程任务完成");}
}