通过等待通知使用 2 个线程生成奇偶数?
Generating odd even numbers using 2 threads via wait notify?
我正在尝试通过等待通知使用 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();
}
}
I am trying to generate odd even numbers using 2 threads via wait notify. But it is only printing 0. Could someone please explain why it is so.
你的问题是 2 个线程都在递增 ai
但它们没有共享同一个变量。因此,当偶数线程吐出 0
并通知 lock
时,奇数线程被唤醒,但它的副本 ai
仍然是 0,所以它又回到睡眠状态。
解决此问题的一种方法是传入 AtomicInteger
而不是 Integer
class。然后当 Even
线程执行 ai.incrementAndGet()
并且 Odd
线程执行 ai.get()
时,它会看到对 ai
.
的更改
如果你不想使用那个 class 那么你需要写一个 MutableInteger
class 如果你想让它们共享同一个变量。
其他一些评论:
- 您的
lock
字段应该是 final
。如果可能的话,实际上所有字段都应该是最终的,但是对于线程程序,final
通常很重要。
- 你可以把
Odd
和Even
写成一样的class,然后传入ai.get() % 2
的预期值。
- 在构造函数中有一个隐含的
super();
,因此可以将其删除。唯一需要显式指定的情况是基 class. 中是否有多个构造函数
- 当你在捕捉
InterruptedException
时,你应该always reinterrupt the thread在捕捉中使用Trread.currentThread().interrupt()
。
我正在尝试通过等待通知使用 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();
}
}
I am trying to generate odd even numbers using 2 threads via wait notify. But it is only printing 0. Could someone please explain why it is so.
你的问题是 2 个线程都在递增 ai
但它们没有共享同一个变量。因此,当偶数线程吐出 0
并通知 lock
时,奇数线程被唤醒,但它的副本 ai
仍然是 0,所以它又回到睡眠状态。
解决此问题的一种方法是传入 AtomicInteger
而不是 Integer
class。然后当 Even
线程执行 ai.incrementAndGet()
并且 Odd
线程执行 ai.get()
时,它会看到对 ai
.
如果你不想使用那个 class 那么你需要写一个 MutableInteger
class 如果你想让它们共享同一个变量。
其他一些评论:
- 您的
lock
字段应该是final
。如果可能的话,实际上所有字段都应该是最终的,但是对于线程程序,final
通常很重要。 - 你可以把
Odd
和Even
写成一样的class,然后传入ai.get() % 2
的预期值。 - 在构造函数中有一个隐含的
super();
,因此可以将其删除。唯一需要显式指定的情况是基 class. 中是否有多个构造函数
- 当你在捕捉
InterruptedException
时,你应该always reinterrupt the thread在捕捉中使用Trread.currentThread().interrupt()
。