等待/通知的相关方法是任意Java对象都具备的,因为这些方法被定义在所有对象的超类java.lang.Object上,方法如下:
方法名称 | 描述 |
---|---|
notify() | 通知一个在对象上等待的线程,使其从main()方法返回,而返回的前提是该线程获取到了对象的锁 |
notifyAll() | 通知所有等待在该对象的线程 |
wait() | 调用该方法的线程进入WAITING状态,只有等待其他线程的通知或者被中断,才会返回。需要注意调用wait()方法后,会释放对象的锁 |
经典范式:
- 等待方遵循如下原则:
1、获取对象的锁。
2、如果条件不满足,那么调用对象的wait()方法,被通知后仍要检查条件。
3、条件满足则执行对应的逻辑任务。
伪代码如下:
synchronized(对象) {
while(条件不满足) {
对象.wait();
}
完成任务逻辑
}
- 通知方遵循如下原则:
1、获得对象的锁。
2、改变条件。
3、通知所有等待在对象上的线程。
伪代码如下:
synchronized(对象) {
改变对象
对象.notifyAll();
}
示例代码:
package concurrent;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* Desc: 等待通知机制
* Creator: pengweixiang
* Date: 2019-03-24
*/
public class WaitNotifyTest
{
private final static Object lock = new Object();
private static AtomicBoolean flag = new AtomicBoolean(true);
public static void main(String[] args)
{
new Thread(new Wait(), "Wait thread").start();
TimeUtils.sleep(1);
new Thread(new Notify(), "Notify thread").start();
}
private static class Wait implements Runnable
{
@Override
public void run()
{
synchronized (lock)
{
while (flag.get())
{
try
{
System.out.println("Current Thread ID: " + Thread.currentThread().getId() + ", Wait waiting ...");
lock.wait();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
System.out.println("Current Thread ID: " + Thread.currentThread().getId() + ", Wait end ...");
}
}
}
private static class Notify implements Runnable
{
@Override
public void run()
{
synchronized (lock)
{
System.out.println("Current Thread ID: " + Thread.currentThread().getId() + ", Notify running ...");
TimeUtils.sleep(3);
flag.compareAndSet(true, false);
lock.notifyAll();
}
TimeUtils.sleep(2);
//再次加锁
synchronized (lock)
{
System.out.println("Current Thread ID: " + Thread.currentThread().getId() + ", Notify end ...");
}
}
}
}
运行结果:
Current Thread ID: 11, Wait waiting …
Current Thread ID: 12, Notify running …
Current Thread ID: 11, Wait end …
Current Thread ID: 12, Notify end …