【问题标题】:Generating odd even numbers using 2 threads via wait notify?通过等待通知使用2个线程生成奇偶数?
【发布时间】:2022-01-20 13:46:19
【问题描述】:

我正在尝试通过等待通知使用 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();
    }
}

【问题讨论】:

    标签: java multithreading wait synchronized notify


    【解决方案1】:

    我正在尝试通过等待通知使用 2 个线程生成奇偶数。但它只打印 0。有人可以解释为什么会这样。

    您的问题是 2 个线程都在递增 ai 但它们不共享同一个变量。因此,当偶数线程吐出0 并通知lock 时,奇数线程会被唤醒,但它的ai 的副本仍为0,因此它会重新进入睡眠状态。

    解决此问题的一种方法是传入 AtomicInteger 而不是 Integer 类。然后当Even 线程执行ai.incrementAndGet() 并且Odd 线程执行ai.get() 时,它会看到ai 的更改。

    如果您不想使用该类,那么您需要编写一个 MutableInteger 类来共享同一个变量。

    几个其他的cmets:

    • 您的lock 字段应为final。如果可能,所有字段都应该是最终字段,但对于线程程序,final 通常很重要。
    • 您可以将OddEven 编写为同一个类,并传入ai.get() % 2 的预期值。
    • 在构造函数中存在隐含的super();,因此可以将其删除。唯一需要明确指定的情况是基类中有多个构造函数。
    • 当你捕捉InterruptedException时,你应该在捕捉always reinterrupt the threadTrread.currentThread().interrupt()

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-08-20
      • 1970-01-01
      • 1970-01-01
      • 2012-04-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多