什么是线程和进程?是如何创建、同步、通信、销毁的?

news/2025/1/12 1:34:23/

计算机系统中,线程和进程是两个基本的概念。多线程编程已经成为现代编程中比较常见的技术,因此对于线程和进程的深刻理解变得尤为重要。

本文将详细介绍线程和进程,包括定义、创建、同步、通信、销毁等方面的内容,并通过实例帮助读者更好地了解这两个概念。

线程

定义

线程(Thread)是指在单个程序中同时执行的一段指令流或执行流程。一个进程可以包含多个线程,每个线程可以执行不同的任务。

在 Java 中,线程是虚拟机中的一种轻量级对象,每个线程拥有自己的执行堆栈和程序计数器(Program Counter,PC),可以独立执行任务。

创建线程

Java 中创建线程有两种方式:

继承 Thread 类并重写 run 方法

public class MyThread extends Thread {public void run() {System.out.println("MyThread running");}
}public static void main(String[] args) {Thread myThread = new MyThread();myThread.start();
}

上面的代码创建了一个新的线程对象 myThread,并启动这个线程。在 MyThread 类中重写 run 方法是为了定义这个线程的执行逻辑。

实现 Runnable 接口并通过 Thread 类创建线程

public class MyRunnable implements Runnable {public void run() {System.out.println("MyRunnable running");}
}public static void main(String[] args) {MyRunnable myRunnable = new MyRunnable();Thread myThread = new Thread(myRunnable);myThread.start();
}

上面的代码创建了一个实现 Runnable 接口的类 MyRunnable,并通过这个类创建了一个线程对象 myThread。在 MyRunnable 类中实现 run 方法是为了定义这个线程的执行逻辑。

线程同步

线程同步是指在多个线程之间协调执行的机制。当多个线程同时访问共享资源时,可能会出现数据不一致的情况。为了避免这种情况,需要使用同步机制来保证数据的一致性。

互斥锁

互斥锁(Mutex)是最常用的一种同步机制。互斥锁可以保证在任何时刻只有一个线程能够进入临界区(Critical Section),从而避免多个线程同时访问共享资源的问题。

在 Java 中,可以使用 synchronized 关键字来实现互斥锁。synchronized 关键字可以应用于方法或者某个代码块,以确保在同一时间只有一个线程可以访问这个方法或者代码块中的内容。

public class Counter {private int count;public synchronized void increment() {count++;}public synchronized int getCount() {return count;}
}

上面的代码定义了一个类 Counter,其中的 incrementgetCount 方法都使用了 synchronized 关键字。这样可以保证在任何时刻只有一个线程能够同时访问这两个方法,从而避免发生数据不一致的情况。

条件变量

条件变量是一种同步机制,可以用于多个线程之间的通信。条件变量通常结合互斥锁一起使用,在等待条件时会释放互斥锁,以便其他线程也可以获取到互斥锁。

在 Java 中,可以使用 waitnotify 方法来实现条件变量。wait 方法可以使当前线程进入等待状态,直到其他线程调用 notify 或者 notifyAll 方法来唤醒这个线程。notify 方法可以随机唤醒一个正在等待的线程,而 notifyAll 方法可以唤醒所有正在等待的线程。

public class MessageQueue {private List<String> queue = new ArrayList<>();public synchronized void put(String message) {queue.add(message);notify();}public synchronized String take() throws InterruptedException {while (queue.isEmpty()) {wait();}return queue.remove(0);}
}

上面的代码定义了一个类 MessageQueue,其中的 put 方法和 take 方法分别用于向队列中添加消息和取出消息。在 take 方法中,如果队列中没有消息,则会进入等待状态,并通过 wait 方法释放互斥锁。在 put 方法中,如果队列中有新的消息,则会通知正在等待的线程从等待状态中唤醒。

线程通信

线程通信是指在多个线程之间传递信息或者数据的机制。线程通信可以通过共享内存或者消息传递来实现。

共享内存

共享内存是一种线程通信的方式,可以让多个线程访问同一块内存区域。在使用共享内存时,需要使用互斥锁来保证数据的一致性。

public class Counter {private int count;public synchronized void increment() {count++;notifyAll();}public synchronized int getCount() throws InterruptedException {while (count == 0) {wait();}int result = count;count = 0;return result;}
}

上面的代码定义了一个类 Counter,其中的 increment 方法用于增加计数器的值,而 getCount 方法用于获取计数器当前的值,并将计数器清零。在 getCount 方法中,如果计数器的值为零,则会进入等待状态,等待其他线程调用 increment 方法来唤醒这个线程。

消息传递

消息传递是一种线程通信的方式,可以让多个线程之间通过消息来进行通信。消息传递有两种方式:共享队列和直接通信。

共享队列

共享队列是一种消息传递的方式,多个线程可以通过一个公共的队列来发送和接收消息。在使用共享队列时,需要使用互斥锁和条件变量来保证数据的一致性。

public class MessageQueue {private List<String> queue = new ArrayList<>();public synchronized void put(String message) {queue.add(message);notify();}public synchronized String take() throws InterruptedException {while (queue.isEmpty()) {wait();}return queue.remove(0);}
}

上面的代码定义了一个类 MessageQueue,其中的 put 方法和 take 方法分别用于向队列中添加消息和取出消息。在 take 方法中,如果队列中没有消息,则会进入等待状态,并通过 wait 方法释放互斥锁。在 put 方法中,如果队列中有新的消息,则会通知正在等待的线程从等待状态中唤醒。

直接通信

直接通信是一种消息传递的方式,多个线程之间通过直接发送消息来进行通信。在使用直接通信时,常用的方式有管道、套接字和消息队列等。

以管道为例,可以使用 PipedInputStreamPipedOutputStream 来实现两个线程之间的通信。

public class PipeDemo {public static void main(String[] args) throws Exception {PipedOutputStream output = new PipedOutputStream();PipedInputStream input = new PipedInputStream(output);Thread t1 = new Thread(() -> {try {output.write("Hello World".getBytes());} catch (IOException e) {e.printStackTrace();}});Thread t2 = new Thread(() -> {try {byte[] buffer = new byte[1024];int len = input.read(buffer);System.out.println(new String(buffer, 0, len));} catch (IOException e) {e.printStackTrace();}});t1.start();t2.start();}
}

上面的代码定义了一个类 PipeDemo,该类通过 PipedOutputStreamPipedInputStream 实现了两个线程之间的通信。在 t1 线程中,向管道中写入了一条消息 “Hello World”;在 t2 线程中,从管道中读取了该消息,并输出到控制台。

销毁线程

线程可以通过调用 interrupt 方法来中断执行,也可以通过设置 volatile 类型的标志位来通知线程退出。当线程不再需要时,可以使用 join 方法等待线程执行完毕并回收资源。

public class StopThreadDemo {private static volatile boolean stop = false;public static void main(String[] args) throws InterruptedException {Thread t = new Thread(() -> {while (!stop) {// do something}});t.start();Thread.sleep(1000);stop = true;t.join();}
}

上面的代码定义了一个类 StopThreadDemo,该类使用 volatile 类型的标志位来通知线程退出。

进程

定义

进程(Process)是计算机中的一个程序关于某个数据集合上的一次运行活动。一个进程可以包含多个线程,每个线程可以执行不同的任务。

在 Java 中,一个进程通常由多个线程组成,可以使用 java.lang.ProcessBuilder 类来创建和控制进程。

创建进程

Java 中可以使用 java.lang.ProcessBuilder 类来创建和控制进程。

public class ProcessDemo {public static void main(String[] args) throws Exception {ProcessBuilder builder = new ProcessBuilder("ls", "-lah");Process process = builder.start();InputStream inputStream = process.getInputStream();BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));String line;while ((line = reader.readLine()) != null) {System.out.println(line);}int exitCode = process.waitFor();System.out.println("Exit code: " + exitCode);}
}

上面的代码创建了一个进程,并执行了 ls -lah 命令。通过读取进程的输入流,可以获取命令执行后的输出结果。调用 waitFor 方法可以等待进程执行完毕并获取进程的退出码。

进程同步

进程同步是指在多个进程之间协调执行的机制。当多个进程同时访问共享资源时,可能会出现数据不一致的情况。为了避免这种情况,需要使用同步机制来保证数据的一致性。

在 Java 中,可以使用管道、共享内存等方式来实现进程同步。以管道为例,可以使用 PipedInputStreamPipedOutputStream 来实现两个进程之间的通信。

进程通信

进程通信是指在多个进程之间传递信息或者数据的机制。进程通信可以通过共享内存或者消息传递来实现。

以管道为例,可以使用 PipedInputStreamPipedOutputStream 来实现两个进程之间的通信。

public class PipeDemo {public static void main(String[] args) throws Exception {Process p1 = new ProcessBuilder("echo", "Hello World").start();Process p2 = new ProcessBuilder("tr", "a-z", "A-Z").start();PipedOutputStream output = new PipedOutputStream(p1.getOutputStream());PipedInputStream input = new PipedInputStream(p2.getInputStream());p1.getOutputStream().close();p2.getInputStream().close();byte[] buffer = new byte[1024];int len;while ((len = input.read(buffer)) != -1) {output.write(buffer, 0, len);}output.close();int exitCode = p1.waitFor();System.out.println("Exit code: " + exitCode);exitCode = p2.waitFor();System.out.println("Exit code: " + exitCode);}
}

上面的代码创建了两个进程 p1p2,在 p1 进程中执行了 echo "Hello World" 命令,在 p2 进程中执行了 tr a-z A-Z 命令。通过管道将 p1 进程的输出和 p2 进程的输入连接起来,从而实现两个进程之间的通信。

销毁进程

进程可以通过调用 destroy 方法来销毁进程。当进程不再需要时,可以调用这个方法来释放所有相关资源。

public class StopProcessDemo {public static void main(String[] args) throws Exception {ProcessBuilder builder = new ProcessBuilder("ping", "-t", "localhost");Process process = builder.start();Thread.sleep(10000);process.destroy();}
}

上面的代码创建了一个进程,并在 10 秒钟后销毁这个进程。


http://www.ppmy.cn/news/220759.html

相关文章

用c#开发安卓程序 (xamarin.android)

作为c#程序员&#xff0c;没有精力和激情去学习java了&#xff0c;又遇到一些项目需要开发手机端&#xff0c;于是我们的networkcomms2.3.1网络通讯框架又要出场了&#xff0c;是的&#xff0c;这是一款来自英国的网络通讯框架&#xff0c;由c#语言编写&#xff0c;其在编写时根…

四大主流新闻App竞品分析

详细内容扫二维码查看&#xff01; 四大主流新闻App竞品分析 1、概述 &#xff08;1&#xff09;市场概况 产品用户体量&#xff1a;2016年Q2移动资讯分发市场用户规模达到5.8亿人&#xff0c;基本完成用户普及&#xff0c;用户增长趋势明显放缓。在活跃用户渗透率方面&#xf…

mysql常用语句

* 数据库概念: * database - 数据库 * 一个数据库包含多张表 * table - 表 * 一个表包含多行多列 * row - 行 * 一行表示一条数据 * column - 列 * 一列表示一项数据* SQL语句 * 概述: * 是多种关系型数据库产品的通用内容 * SQL语句不区分大小写 * 建议所有关键字全部大写 * 分…

开维控制精灵 Ctrl js 华为手机群发短信

开维控制精灵 Ctrl.js 华为手机群发短信 Ctrl.js是基于js语法规则的控制类脚本语言&#xff0c;用于自动化软件测试。 Ctrl.js 需要在手机上下载“开维控制精灵”&#xff0c;应用宝&#xff0c;华为应用市场等平台都可以下载&#xff0c;帮助文档的话可以访问http://ikaiwei…

如何保证项目质量?层层卡点,一次把事情做对!

0 前言 工期太紧&#xff0c;能按期提测不错了&#xff0c;Bug多一点正常。质量好不好&#xff1f;不好说。如何提升&#xff1f;不知道&#xff0c;QA会保证呀。 我的粉丝里大部分程序员对自己代码质量要求还是很高的。可当遇到赶工压力&#xff0c;尤其Deadline前&#xff…

08 【生命周期 组件】

1. 生命周期 1.1 引出生命周期 生命周期 又名生命周期回调函数,生命周期函数、生命周期钩子是什么,Vue在关键时刻帮我们调用的一些特殊名称函数生命周期函数的名字不可更改,但函数的具体内容是根据程序员需求编写的生命周期函数中的this指向的是vm或组件实例对象 <div i…

昨天,小灰做了人生的第一次直播!

熟悉小灰的朋友们都知道&#xff0c;小灰是一个非常腼腆的人。虽然我比较擅长写东西&#xff0c;但完全不擅长口头表达&#xff0c;在公开场合讲话很容易紧张。 因此&#xff0c;对于网上直播&#xff0c;小灰在以前完全不敢想象。 但是&#xff0c;人终究需要成长的。就在昨天…

公司通讯录

部门 职务 姓名 负责事务 联系方式 主管 邓敏丽 西安HR总体事务协调 88825337 专员 汤倩茹 员工沟通、薪酬、异动、转正 88825527 专员 王海静 考勤、离职办理、指纹录入 88825347 专员 高子涵 社保、公积金、户口、档案、员工沟通 88825526 专员 牟尽劲 员工入职、员工档案管理…