当涉及一种场景,线程A需要等待线程B完成工作后再开始工作,这时就需要使用到Object基类中的wait()、notify()和notifyAll()来实现,先上例子
public class text {
volatile static boolean ok = false;
static Object object = new Object();
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
synchronized (object) { // 如果不加锁,会报错IllegalMonitorStateException
System.err.println("进入同步");
while (!ok) {
System.err.println("开始等待");
try {
object.wait();
System.out.println("结束等待");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}).start();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
new Thread(new Runnable() {
@Override
public void run() {
synchronized (object) {
System.out.println("通知停止等待");
ok = true;
object.notifyAll();
}
}
}).start();
}
}
输出结果:
进入同步
开始等待
通知停止等待
结束等待
有几个注意点:
1、要在同步代码(方法)中才可以使用,即要获得对象的锁,才能可以使用该对象wait()、notify()、notifyAll();如果没有在同步代码中就是报IllegalMonitorStateException错误。
note:正因为这种机制的设定,这个三个方法被放在Object基类中,而不是像sleep()方法放在Thread类中,所以当使用sleep()无需在同步代码(方法)中。
2、配合while使用,可以判断是否满足条件,如果不满足就继续等待。例如上面的例子,变量ok,如果不赋值为true,第一条线程将继续等待。
3、notify()和notifyAll()的区别,notify()唤醒其中任意一个正处于等待的线程,而notifyAll()唤醒所有正处等待的线程。所有使用notifyAll()比使用notify()更加安全,严谨。
4、notify()和notifyAll()只能唤醒相应对象的wait()。