线程间通信
1、什么是线程间的通信?
多个线程在处理同一个资源,但是处理的动作(线程任务)却不相同
比如:线程A用来生成包子,线程B用来吃包子,包子可以理解为同一资源,线程A与线程B处理的动作,一个是生产,一个是消费,那么线程A与线程B之间就存在线程通信问题
2、为什么要处理线程间的通信?
多个线程并发执行时,在默认情况下CPU时随机却换线程的,当我么你需要多个线程来共同完成一件任务,并且我们希望他们有规律的执行,那么多线程之间需要一些协调通信,一次来帮我们达到多线程共同操作同一份数据
3、如何保证线程间通信有效利用资源?
多个线程在处理同一个资源,并且任务不同时,需要线程通信来帮助解决线程之间对同一个变量的使用或操作。就是多个线程在操作同一份数据时,避免对同一共享变量的争夺。也就是我们需要通过一定的手段使各个线程能有效的利用资源,而这种手段就是——等待唤醒机制
等待唤醒机制
1、什么是等待唤醒机制?
等待唤醒机制就是多个线程间的一种协作机制,谈到线程我们经常想到的是线程间的竞争,比如各个线程争夺锁,但是多个线程也会有协作的机制,就好比在公司中你与你的同事是竞争关系,但是你们也会合作完成某个项目
等待唤醒机制就是在一个线程进行了规定操作后,另一个线程就进入等待状态(wait()),等待刚刚进行规定操作的线程执行完他们的指定代码后,再将处于等待状态的这个线程唤醒(notify());在有多个线程进行等待的时候,如果需要我们可以使用notifyAll()来唤醒所有的等待线程。
wait/notify就是线程间的一种协作机制
2、等待唤醒机制中的方法
等待唤醒机制就是用于解决线程通信的问题的,使用到的3个方法的含义如下:
① wait方法:线程不再活动,不再参与调度,进入wait set中(一个等待的集合中),因此不会浪费CPU资源,也不会去竞争锁,这时的线程状态为WAITING(等待状态)。处于WAITING状态的线程需要等待别的线程的通知(notify),然后才能从wait set中释放出来,重新进入调度队列(ready queue)
② notify方法:通知在wait set中的一个线程释放,等待时间越久的约先释放
③ notifyAll方法:释放所有在wait set中的全部线程
注意:
哪怕只通知了一个处于等待中的线程,被通知的线程也不能立即回复执行,因为它是在判断了是否含有锁对象发现没有后才中断的,所以他需要再次尝试获取锁(这个过程很可能会面临其他线程的竞争),成功后才能在最开始调用wait方法之后的地方恢复执行
总结:
如果能获取锁,线程就从WAITING状态变成RUNNABLE状态(执行状态);
否则,从wait set出来,又进入entry set,线程就从WAITING状态变成BLOCKED状态(阻塞状态)了
调用wait和notify方法需要注意的细节
- wait方法与notify方法必须要由同一个锁对象调用。因为:对应的锁对象可以通过notify唤醒使用同一个锁对象调用的wait方法后的线程
- wait方法与notify方法是属于Object类的方法。因为:锁对象可以是任意对象,而任意对象的所属类都是继承了Object类的
- wait方法与notify方法必须要在同步代码块或者是同步函数中使用的。因为:必须要通过锁对象调用这两个方法