通过等待通知使用 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 通常很重要。
  • 你可以把OddEven写成一样的class,然后传入ai.get() % 2的预期值。
  • 在构造函数中有一个隐含的 super();,因此可以将其删除。唯一需要显式指定的情况是基 class.
  • 中是否有多个构造函数
  • 当你在捕捉InterruptedException时,你应该always reinterrupt the thread在捕捉中使用Trread.currentThread().interrupt()