当前位置: 首页 > 图灵资讯 > 行业资讯> python 线程间通信用什么手段

python 线程间通信用什么手段

发布时间:2025-04-06 15:44:24

几种实现线程间通信的方法

首先,短信线程之间有两种通信模式:内存共享和消息传输。以下方法基本上是通过这两种模式实现的。让我们分析一下面试中常见的问题:

题目:有两个线程A、B,A线程依次向一个集合中添加元素"abc"字符串一共添加了十次。当添加到第五次时,我希望B线程能收到A线程的通知,然后B线程执行相关的业务操作。

方法一:使用volatile关键词

基于 volatile 实现线程间相互通信的关键词是使用共享内存的想法,一般意味着多个线程同时监控变量,当变量发生变化时 ,线程可以感知和执行相应的业务。这也是实现它最简单的方法。

publicclassTestSync{
//定义共享变量来实现通信,需要volatile修改,否则,线程无法及时感知
staticvolatilebooleannotice=false;
publicstaticvoidmain(String[]args){
List<String>list=newArrayList<>();
///实现线程A
ThreadthreadA=newThread(()->{
for(inti=1;i<=10;i++){
list.add("abc");
System.out.println("线程A在list中添加一个元素,此时list中的元素数为:"+list.size());
try{
Thread.sleep(500);
}catch(InterruptedExceptione){
e.printStackTrace();
}
if(list.size()==5)
notice=true;
}
});
///实现线程B
ThreadthreadB=newThread(()->{
while(true){
if(notice){
System.out.println("线程B收到通知,开始自己做生意...");
break;
}
}
});
// 线程B需要先启动
threadB.start();
try{
Thread.sleep(1000);
}catch(InterruptedExceptione){
e.printStackTrace();
}
///重新启动线程A
threadA.start();
}
}

操作结果如下:

a83ecc68db37c5b7d6428f282ae0232.png

方法二:使用objectwait()和notify()方法

Object提供了线程间通信的方法:wait()、notify()、notifyaAl(),它们是多线程通信的基础,这种实现思想自然是线程间通信。

注意: wait和 notify必须与synchronized一起使用,wait方法释放锁,notify方法不释放锁。

publicclassTestSync{
publicstaticvoidmain(String[]args){
//定义锁对象
Objectlock=newObject();
List<String>list=newArrayList<>();
///实现线程A
ThreadthreadA=newThread(()->{
synchronized(lock){
for(inti=1;i<=10;i++){
list.add("abc");
System.out.println("线程A在list中添加一个元素,此时list中的元素数为:"+
list.size());
try{
Thread.sleep(500);
}catch(InterruptedExceptione){
e.printStackTrace();
}
if(list.size()==5)
lock.notify();///唤醒B线程
}
}
});
///实现线程B
ThreadthreadB=newThread(()->{
while(true){
synchronized(lock){
if(list.size()!=5){
try{
lock.wait();
}catch(InterruptedExceptione){
e.printStackTrace();
}
}
System.out.println("线程B收到通知,开始执行自己的业务...");
}
}
});
// 线程B需要先启动
threadB.start();
try{
Thread.sleep(1000);
}catch(InterruptedExceptione){
e.printStackTrace();
}
///重新启动线程A
threadA.start();
}
}

运行结果如下:

97143b7ba6c5233932aa89016902a56.png

从打印结果截图可以看出,在线程A发出notify()唤醒通知后,线程B仍在完成自己的线程业务后才开始执行,这正好说明,notify()方法不释放锁,wait()方法释放锁。

方法三:使用JUC工具类:使用JUC工具类 CountDownLatch

jdk1.之后在java.util.concurrent包提供了许多与并发编程相关的工具类,简化了我们并发编程代码的写作,***CountDownLatch***基于AQS框架,相当于维护线程间共享变量state。

publicclassTestSync{
publicstaticvoidmain(String[]args){
CountDownLatchcountDownLatch=newCountDownLatch(1);
List<String>list=newArrayList<>();
///实现线程A
ThreadthreadA=newThread(()->{
for(inti=1;i<=10;i++){
list.add("abc");
System.out.println("线程A在list中添加一个元素,此时list中的元素数为:"+list.size());
try{
Thread.sleep(500);
}catch(InterruptedExceptione){
e.printStackTrace();
}
if(list.size()==5)
countDownLatch.countDown();
}
});
///实现线程B
ThreadthreadB=newThread(()->{
while(true){
if(list.size()!=5){
try{
countDownLatch.await();
}catch(InterruptedExceptione){
e.printStackTrace();
}
}
System.out.println("线程B收到通知,开始执行自己的业务...");
break;
}
});
// 线程B需要先启动
threadB.start();
try{
Thread.sleep(1000);
}catch(InterruptedExceptione){
e.printStackTrace();
}
///重新启动线程A
threadA.start();
}
}

运行结果如下:

c3872486eb2a9efa58468a06313fccf.png

方法四:结合Condition,使用Reentrantlock

publicclassTestSync{
publicstaticvoidmain(String[]args){
ReentrantLocklock=newReentrantLock();
Conditioncondition=lock.newCondition();
List<String>list=newArrayList<>();
///实现线程A
ThreadthreadA=newThread(()->{
lock.lock();
for(inti=1;i<=10;i++){
list.add("abc");
System.out.println("线程A在list中添加一个元素,此时list中的元素数为:"+list.size());
try{
Thread.sleep(500);
}catch(InterruptedExceptione){
e.printStackTrace();
}
if(list.size()==5)
condition.signal();
}
lock.unlock();
});
///实现线程B
ThreadthreadB=newThread(()->{
lock.lock();
if(list.size()!=5){
try{
condition.await();
}catch(InterruptedExceptione){
e.printStackTrace();
}
}
System.out.println("线程B收到通知,开始执行自己的业务...");
lock.unlock();
});
threadB.start();
try{
Thread.sleep(1000);
}catch(InterruptedExceptione){
e.printStackTrace();
}
threadA.start();
}
}

运行结果如下:

eab82f92d67dd756f272759a22865dc.png

显然,这种方法使用不是很好,代码编写也很复杂,线程B在被A唤醒后无法立即执行,因为它没有获得锁,也就是说,A在唤醒操作后没有释放锁。这种方法 Object 的 wait() 和 notify() 一样。

方法五:基于LockSuport实现线程之间的阻塞和唤醒

LockSupport 它是一种非常灵活的工具,可以实现线程之间的阻塞和唤醒。它不需要注意是等待线程还是唤醒线程,但需要知道线程的名称。

publicclassTestSync{
publicstaticvoidmain(String[]args){
List<String>list=newArrayList<>();
///实现线程B
finalThreadthreadB=newThread(()->{
if(list.size()!=5){
LockSupport.park();
}
System.out.println("线程B收到通知,开始执行自己的业务...");
});
///实现线程A
ThreadthreadA=newThread(()->{
for(inti=1;i<=10;i++){
list.add("abc");
System.out.println("线程A在list中添加一个元素,此时list中的元素数为:"+list.size());
try{
Thread.sleep(500);
}catch(InterruptedExceptione){
e.printStackTrace();
}
if(list.size()==5)
LockSupport.unpark(threadB);
}
});
threadA.start();
threadB.start();
}
}

运行结果:

fa8af912c46cece6277cad054f0c445.png

python学习网,大量免费python视频教程,欢迎在线学习!

相关文章

如何让vim支持python3

如何让vim支持python3

2025-09-12
python2.7和3.6区别有哪些

python2.7和3.6区别有哪些

2025-09-12
python3有serial库吗

python3有serial库吗

2025-09-12
python中w、r表示什么意思

python中w、r表示什么意思

2025-09-12
python中如何把list变成字符串

python中如何把list变成字符串

2025-09-12
python命名空间是什么

python命名空间是什么

2025-09-12