我的程序有两个Threads,每个都打印十个数字。第一个Thread打印奇数,第二个Thread打印偶数,然后轮流打印数字。我希望得到像1,2,3,4,5 ......这样的序列,直到20,但程序会产生IllegalMonitorStateException。
我知道此Exception的含义,但我在synchronized块中使用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)
我无法弄清楚这一点。有什么想法吗?
答案 0 :(得分:4)
您无法对您不拥有的显示器的对象发送通知:
synchronized (obj1) {
System.out.println(i + Thread.currentThread().getName());
try {
obj2.notify(); // You haven't synchronized on obj2
答案 1 :(得分:3)
如果两个线程一起工作,则它们需要在同一个变量上进行同步。你想要的是等待轮到它运行,然后运行,然后通知另一个线程。
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();
}
}
答案 2 :(得分:0)
在主题0中,您只是在obj2
而不是obj1
上同步notify
。在第二个线程中,它是另一种方式。
答案 3 :(得分:0)
这不会直接回答你的问题,但是线程很低。在您的情况下,您可以使用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();
}
}