java 使用两个线程按顺序打印数字

umuewwlo  于 2023-05-05  发布在  Java
关注(0)|答案(1)|浏览(221)

这是一个面试问题,我不认为它与真实的生活中的实际问题有任何关系。我要打印12345号...顺序地,但条件是我必须使用两个线程打印它,一个负责打印奇数,一个负责打印偶数。
到现在为止,我已经想出了这个解决方案。

package junk.concurrency;

public class PrintEvenOddTester {

    public static void main(String... args) {
        TaskEvenOdd t = new TaskEvenOdd(10);
        Thread t1 = new Thread(t, "odd printer");
        Thread t2 = new Thread(t, "even printer");
        t1.start();
        t2.start();
    }
}

class TaskEvenOdd implements Runnable {

    private int max;
    private boolean isOdd = true;
    private int number = 1;

    TaskEvenOdd(int max) {
        this.max = max;
    }

    synchronized void printEven(int number) { // sync on runnable itself

        while (isOdd) { // if odd is to be printed, wait
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("Even:" + this.number);  // LINE-1
        isOdd = true;
        this.number++;                             // LINE-2
        notifyAll();
    }

    synchronized void printOdd(int number) { // sync on runnable itself
        while (!isOdd) { // if even is to be printed, wait
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("Odd:" + this.number);    // LINE-3
        this.number++;                               // LINE-4
        isOdd = false;
        notifyAll();
    }

    @Override
    public void run() {

        while (number <= max) {

            if (Thread.currentThread().getName().equals("even printer")) {
                printEven(number);
            } else {
                printOdd(number);
            }
        }
    }
}

第一章
在编写这段代码时,我观察到一个奇怪的行为,我不明白。如果在上述代码的第1,2,3,4行,我写number而不是this.number,我的数字示例变量不会递增,代码只是打印无限个1。
我假设printEvenprintOdd方法都是在可运行示例本身上调用的,那么为什么它的值没有增加。我尝试使number易失性,但它仍然导致相同的输出。
我的天
我也看到数字被打印到11,而不是10。我理解为什么会发生这种情况(因为最后一次调用printOdd会被最后一次调用printEven(打印10)通知,因此打印11),避免这种情况的一种方法是每次打印前检查number,看看它是否在限制之下,但我想知道克服这种情况的最佳方法是什么。
谢谢

EDIT方法参数number完全多余,可以省略。这个if(this.max〉=number)条件可以在打印数字之前使用。

3okqufwl

3okqufwl1#

1

你的问题是你的方法的参数也被称为number。所以它在阴影你的班级!所以,当你省略,你inc参数;根本没有任何实际效果!
这个问题有两个解决方案:
1.只需避免这样做(因此,按照惯例,避免使用与参数和字段相同的名称)。
1.使用能够发现此类问题并告诉您的工具。例如,findbugs有明确的规则来告诉你阴影。也许IDE也可以被告知要警告这一点。参见here

鉴于这只是一个“简单”的任务。。在我看来,一个简单的检查“限制”的整体类将是刚刚好。

相关问题