有两个线程的IllegalMonitorStateException
问题描述:
我的程序有两个线程,每个线程打印十个数字。第一条线打印奇数,第二条线打印偶数,然后轮流打印数字。我期待得到像1,2,3,4,5 ....直到20的序列,但程序产生IllegalMonitorStateException。有两个线程的IllegalMonitorStateException
我知道这个异常是什么意思,但我在同步块中使用wait()
和notify()
。这里是我的代码:
public class EvenOddThreadTest {
/**
* @param args
*/
static Object obj1 = new Object();
static Object obj2 = new Object();
static Object obj3=new EvenOddThreadTest();
public static void main(String[] args) throws InterruptedException {
new Thread() {
@Override
public void run() {
for (int i = 1; i < 21; i += 2) {
synchronized (obj1) {
System.out.println(i + Thread.currentThread().getName());
try {
obj2.notify();
obj1.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}.start();
new Thread() {
@Override
public void run() {
for (int i = 2; i < 21; i += 2) {
synchronized (obj2) {
System.out.println(i + Thread.currentThread().getName());
try {
obj1.notify();
obj2.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}.start();
}
}
,这是所产生的异常:
1Thread-0
2Thread-1
Exception in thread "Thread-0" java.lang.IllegalMonitorStateException
at java.lang.Object.notify(Native Method)
at EvenOddThreadTest$1.run(EvenOddThreadTest.java:21)
Exception in thread "Thread-1" java.lang.IllegalMonitorStateException
at java.lang.Object.notify(Native Method)
at EvenOddThreadTest$2.run(EvenOddThreadTest.java:41)
我不知道这一点。有任何想法吗?
答
不能调用notify一个对象,其监测你没有自己的:
synchronized (obj1) {
System.out.println(i + Thread.currentThread().getName());
try {
obj2.notify(); // You haven't synchronized on obj2
答
在线程0你只同步在其上调用notify
的obj2
不obj1
。在第二个线程中,它是相反的。
答
这并不直接回答你的问题,但线程是相当低的水平。在你的情况,例如,你可以使用CyclicBarrier,它将处理同步的细节为您提供:
public class Test {
static CyclicBarrier barrier = new CyclicBarrier(2);
public static void main(String[] args) throws InterruptedException {
new Thread() {
@Override
public void run() {
try {
for (int i = 1; i < 21; i += 2) {
System.out.println(i + Thread.currentThread().getName());
barrier.await();
}
} catch (BrokenBarrierException e) {
//do something
} catch (InterruptedException e) {
//do something
}
}
}.start();
new Thread() {
@Override
public void run() {
try {
for (int i = 2; i < 21; i += 2) {
barrier.await();
System.out.println(i + Thread.currentThread().getName());
}
} catch (BrokenBarrierException e) {
//do something
} catch (InterruptedException e) {
//do something
}
}
}.start();
}
}
答
两个线程都需要在相同的变量进行同步,如果他们一起工作。你想要的是等待轮到它运行,然后运行,然后通知另一个线程。
public class EvenOddThreadTest {
/**
* @param args
*/
static Object obj1 = new Object();
static Object obj3=new EvenOddThreadTest();
public static void main(String[] args) throws InterruptedException {
new Thread() {
@Override
public void run() {
for (int i = 1; i < 21; i += 2) {
synchronized (obj1) {
try {
while (/* not my turn to run *?*/) {
obj1.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(i + Thread.currentThread().getName());
obj1.notify();
}
}
}
}.start();
new Thread() {
@Override
public void run() {
for (int i = 2; i < 21; i += 2) {
synchronized (obj1) {
try {
while (/* not my turn to run *?*/) {
obj1.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(i + Thread.currentThread().getName());
obj1.notify();
}
}
}
}.start();
}
}
这不会控制谁先运行,只是确保两个线程在打印第二个数字之前打印第一个数字。 – 2012-03-02 22:56:07