PSJay Blog

#FIXME, seriously

Java并发总结(四):线程的协作

| Comments

很多时候,一个线程并不能独自完成一个完整的任务,线程之间进行协作是很常见的。在协作的时候,一个线程可能需要等待一个条件为真时才能(再次)开始工作。这个时候,使用while进行忙等待是可以实现功能的,但是其效率存在着很大的问题:毕竟CPU时间片让这些忙等待白白浪费了。这个时候,就需要用到Object的wait(),notify()和notifyAll()这几个方法:

wait():当前线程被挂起,暂时停止继续执行,释放所持有的锁

notify():唤醒当前锁对象的等待队列中的一个线程,如果条件满足,这个线程将会得到执行。

notifyAll():唤醒当前锁对象的等待队列中的所有线程,最终只有一个线程会得到执行。

wait()方法的典型使用模式如下:

1
2
3
4
5
6
7
Object lock = new Object();
synchronized(lock) {
      while(条件不满足) {
           lock.wait();
      }
//正常的业务逻辑
}

值得提醒的是,这三个方法必须在同步方法或者同步块中,因为执行的前提就是当前线程持有锁。如果违反了这条规则,将会抛出一个IllegalMonitorStateException异常。

类比

有一个很合适的生活中得例子可以用来类比这种线程间得协作方法。

比如有老胡,老温,老习要到图书馆借同一本书:《老毛在想什么》。而恰恰图书馆只有一本这样的书了。于是被先到的老胡给借到了。于是等老温和老习来借的时候,他们两老就会碰壁。现在他们有两种做法:1.每天来图书馆问老胡有没有把书给还掉(忙等待)。2.在家等图书馆发出老胡已经把书还掉的通知。显然,第二种做法优于第一种做法。而图书馆发通知也有两种做法:1.只通知老温和老习中的一个人(notify())。2.同时通知老温和老习,谁先到谁就先借(notifyAll())。

Comments