计数器值正在多线程中停止

时间:2019-01-24 15:33:46

标签: java multithreading

我试图在一个线程中打印奇数,在另一个线程中打印偶数。我尝试创建两个线程并在run方法中打印它。

public class OddEven
{
    private final int MAX = 10;
    private static int counter = 0;
    private volatile boolean isOdd = true;

    public synchronized void printEven(int counter)
    {
        try {
            if (!isOdd) {
                System.out.println(Thread.currentThread().getName() + " " + counter);
                counter++;
                isOdd = true;
            }
            wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public synchronized void printOdd(int counter)
    {
        if (isOdd) {
            counter++;
            System.out.println(Thread.currentThread().getName() + " " + counter);
            isOdd = false;
        }
        notifyAll();
    }

    public static void main(String[] args) {
        OddEven oddEven = new OddEven();

        Thread th1 = new Thread() {
            public void run() {
                while (OddEven.counter < oddEven.MAX) {
                    oddEven.printEven(OddEven.counter);
                }
            }
        };
        th1.setName("even -");
        th1.start();

        Thread th2 = new Thread() {
            public void run() {
                while (OddEven.counter < oddEven.MAX) {
                    oddEven.printOdd(OddEven.counter);
                }
            }
        };
        th2.setName("odd -");
        th2.start();
    }
}

但是它无限打印如下。

even - 0
odd - 1
even - 0
odd - 1
even - 0
odd - 1

2 个答案:

答案 0 :(得分:2)

阅读:Is Java "pass-by-reference" or "pass-by-value"?

  1. 您传入了一个原语。 counter++;仅在方法内有意义,对外部世界没有影响。 count是指方法参数,而不是字段this.count

  2. 条件OddEven.counter < oddEven.MAX上没有适当的同步,因此可能会发生不同的情况。

我的建议是删除isOdd并当场检查。例如,

public synchronized void printEven() {
    if (counter % 2 != 0) {
        System.out.println(Thread.currentThread().getName() + " " + ++counter);
    }
}

答案 1 :(得分:0)

oddEven.printEven(OddEven.counter)行将一个值按整数传递给printEven方法,该方法在执行OddEven.counter时不会更改counter++的值,这也在其他答案中指出

要获得所需的输出,一种选择是删除传递给printEvenprintOdd方法的参数。还有许多其他方法可以实现您在这里想要做的事情。

printEven方法中也有一个错误。 counter++;必须在打印语句之前。

这将为您提供所需的输出。