python 线程通信的几种方式,python主线程和子线程如何通信

  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的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: