Этот вопрос на интервью, и я не думаю, что он имеет какое-либо отношение к практическим проблемам реальной жизни. Я должен печатать числа 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);
}
}
}
}
при написании этого кода я заметил один странное поведение, которое я не понял. Если на LINE-1,2,3,4 в приведенном выше коде я пишу number
вместо this.number
, то переменная экземпляра моего номера не увеличивается, а код просто печатает бесконечное число единиц.
Я предполагаю, что и метод printEven
, и printOdd
вызван на сам исполняемый экземпляр, а затем почему его значение не увеличивается. Я пробовал делать number
летучих, но все же результат был таким же.
Также я вижу цифры становятся печататься до 11 не до 10. Я понимаю, почему это происходит (как последний вызов printOdd получает уведомление по последнему зову printEven (который печати 10), таким образом, выводит 11) , один из способов избежать этого - проверять число каждый раз перед печатью и посмотреть, ограничено ли это, но я хотел знать, что было бы лучшим способом преодолеть это.
Спасибо.
РЕДАКТИРОВАТЬ параметр метода number
полностью избыточными и могут быть опущены. Это условие if (this.max> = number) может использоваться перед печатью номера.
Если я когда-либо задаю этот вопрос в интервью, я хочу сказать: «Это очень глупое дело. Если вы хотите, чтобы какая-либо программа выполняла последовательность вещей в определенном порядке, правильный способ сделать это случится, это сделать все вещи в _one thread_. " Если кто-нибудь когда-нибудь задает мне этот вопрос, а затем говорит: «Хорошо, но делайте это в любом случае», я создам общее решение, в котором любое количество потоков по очереди передаёт токен от одного к другому через «BlockingQueues»: Когда поток получает токен, его очередь. Когда это будет сделано, он передает токен следующему потоку. –