public class Test2 {
private static volatile Boolean aBoolean = true;
static class A implements Runnable{
@Override
public void run() {
synchronized (aBoolean){
while (aBoolean){
try {
System.out.println("进入A, 等待中");
aBoolean.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("A over");
}
}
}
static class B implements Runnable{
@Override
public void run() {
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (aBoolean){
System.out.println("通知A可以运行了");
aBoolean = false;
aBoolean.notifyAll();
//Boolean.TRUE.notifyAll();
}
}
}
public static void main(String[] args) {
new Thread(new A()).start();
new Thread(new B()).start();
}
}
运行结果:
进入A, 等待中
通知A可以运行了
Exception in thread "Thread-1" java.lang.IllegalMonitorStateException
at java.lang.Object.notifyAll(Native Method)
at Test2$B.run(Test2.java:39)
at java.lang.Thread.run(Thread.java:748)
由于我们会给aBoolean重新赋值, 导致对象监视器改变, 因为false和true这两个常量对应着两个不同的对象。当aBoolean产生变化时,很可能导致不同的线程同步了不同的对象
解决方法:
将这一行 aBoolean.notifyAll(); 改为: Boolean.TRUE.notifyAll();
或者是用显示锁ReentrantLock的方式