java多线程之等待通知经典范式
1:运行过程
上图所示是两个线程WaitThread和NotifyThread线程的工作状态图,其中WaitThread线程和NotifyThread线程的功能逻辑如下;前者检查flag是否为false,如果符合要去,继续后续操作,如果不满足则继续在Object.wait等待。后者线程,在睡眠了一段时候后,同时通知Object对象上的等待的线程。当然要修改flag符合WaitThread的工作情况。
上述的工作流程如下;WaitThread线程首先获得对象的锁,然后判断自己的继续运行的flag条件是否满足(while(!flag){ }),如果不满足则调用Object.wait()的方法,从而放弃对象的锁,进入Object对象的等待队列里。由于WaitThread释放了Object对象的锁,所以NotifyThread线程可以获得Object的锁,并修改flag,同时调用Object.notify()方法,然后将WaitThread线程调入同步队列中,将WaitThread的状态有等待变为阻塞。等NotifyThread线程释放锁以后,WaitThread线程再次获得锁并从wait方法返回,然后判断flag,如果满足则进入后续的工作状态。
2:经典范式
这里总结常用的等待/通知的伪代码,从上面我们总结等待放/通知者的经典范式,分别针对这等待放(消费者)和通知方(生产者)。
2.1:等待方
等待方遵循如下原则
- 获取对象的锁。
- 如果条件不满足,那么调用对象的wait()方法,进入等待状态。被通知后依然还要检查条件漫步满不满足(这就是要使用while()进行判断的原因,即便从wait方法返回,也要不断地检查条件是否满足)。
- 条件满足,则执行对应的逻辑。
对应伪代码如下:
synchronized(对象){ while(条件不满足){ 对象.wait(); } 条件满足的逻辑处理 }
2.2:通知者
通知方遵循如下原则
- 获取对象的锁。
- 改变条件(flag)
- 通知所有在该对象等待的线程。
synchronized(对象){ 改变条件 对象.notifyAll() }