本文共 5552 字,大约阅读时间需要 18 分钟。
进程是程序运行的核心单元,是系统资源分配和调度的基本单位。每个进程都有独立的代码和数据空间,进程间切换会产生一定的开销。
进程的特点
进程是一个程序的一次执行实例,通常包含代码段、数据段和堆栈段。它是系统调度的基本单位。多进程环境
多进程允许多个任务同时运行,通过系统调度将CPU资源分配给各个进程。线程是进程中的一个独立执行单元,是CPU调度的基本单位。与进程相比,线程具有更小的粒度,线程切换开销更低。
线程的定义
线程是进程中的一个执行实体,负责执行包含在进程地址空间中的代码。每个线程有自己的运行栈和程序计数器,但共享进程的其他资源。线程的作用
线程允许多个任务在进程内部同时执行,提升系统效率。独立性
进程可以独立地分配和管理资源。动态性
进程的状态可以随着运行环境发生改变。并发性
多个进程可以同时运行,通过系统调度实现并发执行。通过不同的方式可以启动新的进程,以下是常用的两种方法:
ProcessBuilder pb = new ProcessBuilder("cmd", "/c", "ipconfig/all");Process p = pb.start();// 读取进程输出BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));while ((temp = br.readLine()) != null) { System.out.println(temp);}
String cmd = "cmd " + "/c " + "ipconfig/all";Process process = Runtime.getRuntime().exec(cmd);// 读取进程输出BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));while ((temp = br.readLine()) != null) { System.out.println(temp);}
// 删除已存在的文件File f = new File("T1.java");if (f.exists()) { f.delete();}// 生成代码文件PrintWriter pw = new PrintWriter(new FileWriter("T1.java"));pw.println("public class T1 {");pw.println("public static void main(String[] args) throws Exception {");pw.println("System.out.println(\"Hello Java!\");");pw.println("}}");pw.close();// 编译代码Process process = Runtime.getRuntime().exec("cmd /c javac T1.java");// 执行已编译的类process = Runtime.getRuntime().exec("cmd /c java T1");
线程可以通过不同的方式实现,以下是常用的四种方法:
public class LeftThread extends Thread { public void run() { for (int i = 0; i < 50; i++) { System.out.println("左手一个慢动作..."); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } }}// 启动线程Thread t1 = new LeftThread();t1.start();
public class RightRunnable implements Runnable { public void run() { for (int i = 0; i < 50; i++) { System.out.println(Thread.currentThread().getName() + ":右手慢动作重播!"); } }}// 启动线程Thread t2 = new Thread(new RightRunnable());t2.start();
public class MyCallable implements Callable{ private int begin; private int end; public MyCallable(int begin, int end) { this.begin = begin; this.end = end; } public Integer call() throws Exception { System.out.println(Thread.currentThread() + "---" + begin + ".." + end); int res = 0; for (int i = begin; i <= end; i++) { res += i; } return res; }}// 使用FutureTask创建线程FutureTask ft = new FutureTask (new MyCallable(1, 100));Thread t = new Thread(ft);t.start();int sum = ft.get();
public class T1 { public static void main(String[] args) throws Exception { ExecutorService es = Executors.newFixedThreadPool(3); Future[] fs = new Future[10]; for (int i = 0; i < 10; i++) { Callablecaller = new MyCallable(i * 1000 + 1, (i + 1) * 1000); fs[i] = es.submit(caller); } int res = 0; for (int i = 0; i < fs.length; i++) { Object obj = fs[i].get(); if (obj instanceof Integer) { res += (Integer) obj; } } es.shutdown(); System.out.println("Main:" + res); }}
线程池通过管理线程的生命周期,优化了线程资源的使用。常用的线程池实现包括:
ExecutorService es = Executors.newFixedThreadPool(3);// 创建多个Callable任务,并提交到线程池for (int i = 0; i < 10; i++) { Callable task = () -> { // 实现具体的任务逻辑 try { // 假设任务涉及计算 System.out.println("正在计算:" + i); Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } }; Future future = es.submit(task); // 等待任务完成 future.get();}es.shutdown();
ExecutorService es = Executors.newCachedThreadPool();for (int i = 0; i < 100; i++) { Callable task = () -> { System.out.println("新任务提交:" + i); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } }; Future future = es.submit(task); // 等待任务完成 future.get();}es.shutdown();
线程间的通信和同步至关重要,以下是一些常用的机制:
synchronized 关键字
可以锁定特定方法或代码块,防止多个线程同时访问。Lock 接口
使用第三方库如LockUtils实现更细粒度的锁。Wait/Notify
通过等待和通知机制实现线程间的同步。CountDownLatch
用于等待多个线程的完成。CyclicBarrier
用于多个线程在完成各自任务后,等待于一个共同的点。线程的终止需要谨慎处理,以避免资源泄漏。系统提供了以下机制:
public class T1 implements Runnable { private boolean running = true; public void run() { try { while (running) { System.out.println("线程在运行"); Thread.sleep(100); } } catch (InterruptedException e) { e.printStackTrace(); } } public static void main(String[] args) { Thread t = new Thread(new T1()); try { Thread.sleep(2000); running = false; } catch (InterruptedException e) { e.printStackTrace(); } t.interrupt(); t.join(); System.out.println("线程已终止"); }}
孤儿进程和僵尸进程是多线程环境中的常见问题,需要妥善处理:
孤儿进程
当父进程退出而子进程仍在运行时,孤儿进程会被init进程收养。僵尸进程
当子进程退出但父进程未释放资源时,僵尸进程会占用系统资源,需及时回收。并行
多个处理器同时执行相同任务,真正意义上的同时执行。并发
通过时间片轮转,使得看起来多个任务同时执行,但实际上是交替执行的。资源利用更高效
线程的创建和切换开销较低。吞吐量更高
CPU资源得到充分利用,减少空转时间。扩展性更好
通过增加处理器核心,系统性能得到显著提升。多线程编程是一种强大的编程范式,通过合理利用系统资源,可以显著提升程序的性能和响应速度。在实际应用中,选择合适的线程和同步机制至关重要,以确保程序的健壮性和稳定性。
转载地址:http://xbbdz.baihongyu.com/