以下两个是Java提供用于协调线程之间的操作接口,并且是定义在Object中:
public final void wait() throws InterruptedException
public final native void notify()
此两个方法的调用必须先获取监视器,即在synchronzied语句中调用。
必须使用锁来调用方法,否则会出现 IllegalMonitorStateException 异常
因为一个线程在调用object.wait()后会释放所持有的监视器,并进入等待队列中。
而另一条线程在调用object.notify()后需该线程释放所持有的锁后被唤醒的线程才能争夺到锁资源继续工作。
public class MyStack1 {
private static final Object lock = new Object();
public static class Producer extends Thread {
@Override
public void run() {
synchronized (lock) {
System.out.println(System.currentTimeMillis() + ": producer start!");
try {
System.out.println(System.currentTimeMillis() + ": producer wait!");
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(System.currentTimeMillis() + ": producer shop!");
}
}
}
public static class Consumer extends Thread {
@Override
public void run() {
synchronized (lock) {
System.out.println(System.currentTimeMillis() + ": consumer start and notify producer");
lock.notify();
System.out.println(System.currentTimeMillis() + ": consumer shop!");
try {
//让结果的时间戳更容易观察
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String args[]) throws InterruptedException {
Thread producer = new Producer();
Thread consumer = new Consumer();
producer.start();
//这里是为了让producer先执行
Thread.sleep(2000);
consumer.start();
}
}
1517143096608: producer start!
1517143096608: producer wait!
1517143098621: consumer start and notify producer
1517143098621: consumer shop!
1517143099629: producer shop!
当线程producer调用wait() 后会释放锁资源并进入等待队列中进行等待。
随后Consumer调用notify() 后就会唤醒等待队列中的线程,如果等待队列中有多条线程则由线程规划器随机挑选唤醒。调用此方法不会释放锁资源。
被唤醒的线程会等待其他线程释放锁资源(如调用notify()的线程),之后只有获取到锁后才能继续执行下去。
public final native void notifyAll()
notify() 一次只能随机叫醒一个人,而notifyAll() 却能炸醒所有人。
与notify() 的差异在与notifyAll() 是一次性将在等待队列中的所有线程全部唤醒,然后让被唤醒线程们进行争夺锁资源。