import java.util.concurrent.TimeUnit;
public class WaitNotify {
static Object lock = new Object();
static boolean wasSignalled = false;//为了避免信号丢失
public static void main(String[] args) throws Exception{
Thread waitThread = new Thread(new Wait(), "WaitThread");
waitThread.start();
TimeUnit.SECONDS.sleep(1);
Thread notifyThread = new Thread(new Notify(), "NotifyThread");
notifyThread.start();
}
static class Wait implements Runnable {
@Override
public void run() {
synchronized (lock) {
while(!wasSignalled) {//使用while有两点作用:
//1、进入wait()前检查wasSignalled变量,以确认没有被notify过,才进入wait
//2、防止假唤醒。等待线程即使没有收到正确的信号,也能执行后面的操作,这可能导致严重的问题。使用了while循环,可使等待线程在没有收到
//wasSignalled为true的信号时一直等待。ps:jvm实现等待线程的自旋会严重消耗cpu,慎重使用!
try {
System.out.println("WaitThread获得锁,进行wait");
lock.wait();
} catch (InterruptedException e) {}
}
//线程被唤醒之后,设置自己没有被通知过
//如果有多个线程被唤醒,由于第一个线程已经把wasSignalled设置为false,所以其他线程在while判断后,只能等待,等待下一次通知信号
wasSignalled = false;
System.out.println("等待线程被唤醒---完成自己的工作");
}
}
}
static class Notify implements Runnable {
@Override
public void run() {
synchronized (lock) {
System.out.println("Notify 线程获得锁,进行通知");
wasSignalled = true;
lock.notifyAll();//将等待队列中所有的线程移动到同步队列。直到当前线程释放了锁以后,等待线程才能从wait方法返回
}
}
}
}
WaitThread线程:
1、获取对象的锁
2、如果条件不满足,那么调用对象的wait方法,被通知后扔要检查条件
3、条件满足,则执行自己的逻辑