### 1、线程的等待/通知机制
#### 1.1、介绍
等待/通知机制是指一个线程A调用了对对象O的wait()方法进入等待状态,而另一个线程B调用了对象O的notify()或者notifyAll()方法,线程A收到通知后从对象O的wait()方法返回,执行后续操作。上述两个线程通过对象O来完成交互,而对象上的wait()和notify()/notifyAll()的关系如同开关信号一样,用来完成等待方和通知方之间的交互工作。
等待/通知的相关方法是任意java对象都具备的,因为这些方法被定义在所有对象的超类java.lang.Object上,相关方法如下表:
|方法名|描述|
|-------|-------|
|notify()|唤醒正在此对象监视器上等待的单个线程。如果任何线程正在等待此对象,则选择其中一个线程被唤醒。选择是任意的,由实施决定。|
|notifyAll()|唤醒等待此对象监视器的所有线程。|
|wait()|调用该方法的线程进入WAITING状态,只有等待另外线程的通知或被中断才会返回,需要注意,调用wait()方法后,会释放对象的锁。|
|wait(long)|超时等待一段时间,如果在等待时间内没有被通知就超时返回;这里的时间单位是毫秒。|
|wait(long, int)|对超时时间更细粒度的控制,可以达到纳秒|
#### 1.2、使用注意事项
调用wait()、notify()以及notifyAll()方法时需要注意的事项有:
- 使用wait()、notify()以及notifyAll()方法需要先对调用对象加锁;
- 调用wait()方法后,线程状态由RUNNING变为WAITING,并将当前线程放置到对象的等待队列中。
- notify()和notifyAll()方法被调用后,等待线程依旧不会从wait()方法返回,只有当调用notify()和notifyAll()方法的线程释放锁之后,等待线程才有机会从wait()返回。
- notify()方法将等待队列中的一个线程从等待队列中移动到同步队列中,而notifyAll()方法将等待队列中的所有线程全部移动到同步队列,被移动的线程状态由WAITING变为BLOCKED。
- 从wait方法返回的前提是获得了调用对象的锁。
#### 1.3、等待/通知机制的典型范式
等待/通知机制的典型范式分为两部分,分别针对等待方(消费者)和通知方(生产者)
**等待方遵循如下原则:**
- 获取对象的锁。
- 如果条件不满足,调用对象的wait()方法,被通知后任要检查条件。
- 条件满足执行对应的逻辑。
```
synchronized(对象){
while(条件不满足){
对象.wait();
}
对应处理的逻辑;
}
```
**通知方遵循如下原则:**
- 获取对象的锁。
- 改变条件。
- 通知所有等待在对象上的线程。
```
synchronized(对象){
改变条件;
对象.notifyAll();
}
```
### 2、Thread.join()方法的使用
如果一个线程执行了join()方法,那么需要等到该线程终止后才从join()方法返回。线程除了提供join()方法外,还提供了join(long millis)和join(long millis, int nanos)两个具备超时特性的方法,这两个超时方法表示,如果线程在给定的超时时间内没有终止,那么将会从该超时方法中返回。其中join(0)表示永远等待,相当于wait()。

Java并发编程学习笔记(二)