线程通信

 

多个线程协同工作来完成某个任务,这时就涉及到了线程间通信了; 可能会涉及到协同使用共同资源

默认情况下CPU是随机切换线程的,当需要多个线程共同完成任务就是要共享资源,如何协调多个线程对同一资源的竞争.这个时候就必须要线程之间通信进行协调通信控制执行顺序,等待和唤醒的协调,谁等待,谁执行

线程通信是指一个线程在进行了规定了之后就进入等待状态,等待其他的线程执行完毕,再将其唤醒.

 

如果是同步监视器

线程的等待唤醒机制是wait(),notify();具体是sychronized+wait+notify;一般而言必须是由同步监视器来调用的,只能在同步方法或者同步代码块中使用。

同步方法,this对象调用;同步关键字,则(obj)里的obj调用。总而言之,就是同步监视器对象进行调用。

如果不是sychronized写法,就需要使用条件变量condition

 

使用条件变量

同步监视器,锁是隐式的,当前的锁对象来调用wait,notify,notifyall方法,进行线程通信  这些方法是object对象提供的,所以只能在sychronized的时候使用,因为sychronized的锁就是java对象锁。锁是隐式的,条件变量也是隐式的。对象锁来调用wait方法,释放了锁(当前对象锁),等待的也就是当前这个对象锁。

所以,可以理解这三个方法是对象级别,Lock,使用condition来绑定,锁的条件对象,await,signal,signalAll

 

使用juc提供的阻塞队列

多线程环境中,通过队列可以很容易实现数据共享,比如经典的“生产者”和“消费者”模型中,通过队列可以很便利地实现两者之间的数据共享。假设我们有若干生产者线程,另外又有若干个消费者线程。如果生产者线程需要把准备好的数据共享给消费者线程,利用队列的方式来传递数据,就可以很方便地解决他们之间的数据共享问题。但如果生产者和消费者在某个时间段内,万一发生数据处理速度不匹配的情况呢?理想情况下,如果生产者产出数据的速度大于消费者消费的速度,并且当生产出来的数据累积到一定程度的时候,那么生产者必须暂停等待一下(阻塞生产者线程),以便等待消费者线程把累积的数据处理完毕,反之亦然。

强大的concurrent包横空出世了,强大的BlockingQueue。(在多线程领域:所谓阻塞,在某些情况下会挂起线程(即阻塞),一旦条件满足,被挂起的线程又会自动被唤醒)

 

BlockingQueue队列 可以作为线程通信的工具  

如果已满put 放不用进去而且会阻塞add抛异常,offer返回布尔false且元素无法被放入队列,但不阻塞当前线程;

如果已空take拿不出来而且阻塞,remove抛异常,poll返回布尔false且无法删除

利用阻塞队列的特性进行线程通信

场景:生产者和消费者的速度不一样,可以使用阻塞队列来处理,delayQueue

 

有五个实现类

基于数组ArrayBlockingQueue

基于链表LinkedBlockingQueue

基于链表DelayQueue??? 延迟队列

DelayQueue中的元素只有当其指定的延迟时间到了,才能够从队列中获取到该元素。DelayQueue是一个没有大小限制的队列,因此往队列中插入数据的操作(生产者)永远不会被阻塞,而只有获取数据的操作(消费者)才会被阻塞。

使用场景:DelayQueue使用场景较少,但都相当巧妙,常见的例子比如使用一个DelayQueue来管理一个超时未响应的连接队列。

 

 

应用举例:

  1. 如何让两个线程依次执行?

  2. 那如何让 两个线程按照指定方式有序交叉运行呢?

  3. 四个线程 A B C D,其中 D 要等到 A B C 全执行完毕后才执行,而且 A B C 是同步运行的

  4. 三个运动员各自准备,等到三个人都准备好后,再一起跑

  5. 子线程完成某件任务后,把得到的结果回传给主线程

 

参考:  https://mp.weixin.qq.com/s/CQKIsJ1IR89oiCfh3ARzZw

 

posted @ 2021-04-20 14:58  加瓦加瓦  阅读(209)  评论(0编辑  收藏  举报