这是一个面试问题,我不认为它与真实的生活中的实际问题有任何关系。我要打印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。
我假设printEven
和printOdd
方法都是在可运行示例本身上调用的,那么为什么它的值没有增加。我尝试使number
易失性,但它仍然导致相同的输出。
我的天
我也看到数字被打印到11,而不是10。我理解为什么会发生这种情况(因为最后一次调用printOdd会被最后一次调用printEven(打印10)通知,因此打印11),避免这种情况的一种方法是每次打印前检查number,看看它是否在限制之下,但我想知道克服这种情况的最佳方法是什么。
谢谢
EDIT方法参数number
完全多余,可以省略。这个if(this.max〉=number)条件可以在打印数字之前使用。
1条答案
按热度按时间3okqufwl1#
1
你的问题是你的方法的参数也被称为number。所以它在阴影你的班级!所以,当你省略,你inc参数;根本没有任何实际效果!
这个问题有两个解决方案:
1.只需避免这样做(因此,按照惯例,避免使用与参数和字段相同的名称)。
1.使用能够发现此类问题并告诉您的工具。例如,findbugs有明确的规则来告诉你阴影。也许IDE也可以被告知要警告这一点。参见here。
二
鉴于这只是一个“简单”的任务。。在我看来,一个简单的检查“限制”的整体类将是刚刚好。