我试图生成奇偶数使用2个线程通过等待通知。但它只是打印0。
有人能解释一下为什么会这样吗。
下面是我的代码:
package waitNotify2;
class Odd implements Runnable {
Object lock;
volatile Integer ai;
public Odd(Object lock, Integer ai) {
super();
this.lock = lock;
this.ai = ai;
}
@Override
public void run() {
synchronized(lock) {
while(true) {
while(ai % 2 == 0) {
try {
lock.wait();
} catch(InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(ai + " ");
ai++;
lock.notify();
}
}
}
}
class Even implements Runnable {
Object lock;
volatile Integer ai;
public Even(Object lock, Integer ai) {
super();
this.lock = lock;
this.ai = ai;
}
@Override
public void run() {
synchronized(lock) {
while(true) {
while(ai % 2 == 1) {
try {
lock.wait();
} catch(InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(ai + " ");
ai++;
lock.notify();
}
}
}
}
public class PrintOddEven2 {
// Driver Code
public static void main(String[] args) {
Object o = new Object();
Integer i = 0;
Odd odd = new Odd(o,i);
Even even = new Even(o,i);
Thread t1 = new Thread(odd);
Thread t2 = new Thread(even);
t1.start();
t2.start();
}
}发布于 2022-03-01 18:40:16
我试图生成奇偶数使用2个线程通过等待通知。但它只是打印0。有人能解释一下为什么会这样吗。
您的问题是,这两个线程都在递增ai,但它们没有共享相同的变量。因此,当偶数线程发出0并通知lock时,奇怪的线程会醒来,但它的ai副本仍然是0,所以它会回到休眠状态。
解决这个问题的一种方法是传入一个AtomicInteger,而不是Integer类。然后,当Even线程执行ai.incrementAndGet()而Odd线程执行ai.get()时,它将看到对ai的更改。
如果不想使用该类,则需要编写一个MutableInteger类,如果您希望它们共享相同的变量。
其他几点评论:
lock字段应该是final。实际上,如果可能的话,所有字段都应该是最终的,但是对于线程程序来说,final作为一条规则是很重要的。Odd和Even作为同一个类编写,并传递ai.get() % 2的期望值。super();,因此可以删除它。惟一需要显式指定它的时间是基类中是否有多个构造函数。InterruptedException时,您应该在总是重新中断线程中使用Trread.currentThread().interrupt()。https://stackoverflow.com/questions/70787349
复制相似问题