JavaSE 两个线程交替输出数字时,发生了IllegalMonitorStateException。:
原代码
public class WaitEx {
public static void main(String[] args) {
Integer i=1;//自动装箱
Thread t2=new Thread1(i);
Thread t3=new Thread2(i);
t2.setName("第一进程");
t3.setName("第二进程");
t2.start();
t3.start();
}
}
class Thread1 extends Thread {
Integer i;
public Thread1( Integer i) {
this.i=i;
}
@Override
public void run() {
while(i.<100) {
synchronized (i) {
if (i% 2 == 0) {
try {
i.wait();//为偶数时等待
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + " " + i);
i++;//自加一
i.notifyAll();//唤醒
}
}
}
}
class Thread2 extends Thread {
Integer i;
public Thread2(Integer i) {
this.i = i;
}
@Override
public void run() {
while(i<100) {
synchronized (i) {
if (i % 2 == 1) {
try {
i.wait();//为奇数时等待
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + " " + i);
i++;
i.notifyAll();//唤醒
}
}
}
}
执行结果
通过翻阅API,此异常发生的情况为
- 抛出表示线程已试图在对象的监视器上等待或通知其他线程在等待对象的监视器上,而不拥有指定的监视器。
- 会出现在Object.notify(), Object.notifyAll(), Object.wait(), Object.wait(long), Object.wait(long, int), Serialized Form
初步推测
System.out.println(Thread.currentThread().getName() + " " + i);
i++;//自加一
i.notifyAll();//唤醒
初步推测:通过API可以推测出此异常一般发生在没有synchronized同步下,而原代码已经synchronized了,所以推测应该是i进行 自加1 运算时,创建了一个新的Integer对象,唤醒时已经不是原来synchronized约束的那个Integer对象了。推测可能同样的异常也会发生在String和Boolean上。
解决方案
通过API文档,找到了AtomicInteger类
通过其IncrementAndGet方法可以实现自加1并不创建新的对象;
修改后代码
public class Wait {
public static void main(String[] args) {
AtomicInteger i=new AtomicInteger(1);//自动装箱
Thread t2=new Thread1(i);
Thread t3=new Thread2(i);
t2.setName("第一进程");
t3.setName("第二进程");
t2.start();
t3.start();
}
}
class Thread1 extends Thread {
AtomicInteger i;
public Thread1( AtomicInteger i) {
this.i=i;
}
@Override
public void run() {
while(i.get()<100) {
synchronized (i) {
if (i.get() % 2 == 0) {
try {
i.wait();//为偶数时等待
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + " " + i.get());
i.incrementAndGet();//自加一
i.notifyAll();//唤醒
}
}
}
}
class Thread2 extends Thread {
AtomicInteger i;
public Thread2(AtomicInteger i) {
this.i = i;
}
@Override
public void run() {
while(i.get()<100) {
synchronized (i) {
if (i.get() % 2 == 1) {
try {
i.wait();//为奇数时等待
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + " " + i.get());
i.incrementAndGet();
i.notifyAll();//唤醒
}
}
}
}
输出结果