python 线程通信的几种方式,python主线程和子线程如何通信
线程间通信的几种实现方式
首先,短信线程之间的通信有两种模式:共享内存和消息传递。下面的方法基本都是由这两个模型实现的。我们来分析一个常见的面试话题:
题目:有两个线程A,B,一个线程把元素‘ABC’字符串依次加到一个集合中,一共加了十次。添加到第五次的时候,希望线程B能收到线程A的通知,然后线程B进行相关的业务操作。
方式一:使用volatile关键字
基于volatile关键字的线程间通信是使用共享内存的思想,大致意思是多个线程同时监听一个变量。当这个变量发生变化时,线程可以感知并执行相应的业务。这也是最简单的实现方式。
publicsclasstestsync {
//定义一个共享变量实现通信。需要用volatile来修饰,否则线程无法及时感知。
staticvolatilebooleanotice=false;
publicstaticvoidmain(String[]args){
ListStringlist=new ArrayList();
//实现线程a
ThreadthreadA=newThread(()-{
for(inti=1;i=10i ){
list . add( ABC );
System.out.println(线程A在列表中增加一个元素,列表中元素个数为: list . size());
尝试{
thread . sleep(500);
} catch(interrupted exception){
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();
}
}运行结果为:
方式二:使用Object类的wait()和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();
}
}
由打印结果截图可知,在线程A发出notify()唤醒通知之后,依然是走完了自己线程的业务之后,线程B才开始执行,这也正好说明了,notify()方法不释放锁,而wait()方法释放锁。
方式三:使用JUC工具类 CountDownLatch
jdk1.5之后在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();
}
}
方法四:使用ReentrantLock结合Condition
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();
}
}
显然这种方式使用起来并不是很好,代码编写复杂,而且线程B在被A唤醒之后由于没有获取锁还是不能立即执行,也就是说,A在唤醒操作之后,并不释放锁。这种方法跟 Object 的 wait() 和 notify() 一样。
方式五:基于LockSupport实现线程间的阻塞和唤醒
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();
}
}
盛行IT软件开发工作室,大量的免费python视频教程,欢迎在线学习!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。