2016-08-13 3 views
-1

Этот вопрос на интервью, и я не думаю, что он имеет какое-либо отношение к практическим проблемам реальной жизни. Я должен печатать числа 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) может использоваться перед печатью номера.

+0

Если я когда-либо задаю этот вопрос в интервью, я хочу сказать: «Это очень глупое дело. Если вы хотите, чтобы какая-либо программа выполняла последовательность вещей в определенном порядке, правильный способ сделать это случится, это сделать все вещи в _one thread_. " Если кто-нибудь когда-нибудь задает мне этот вопрос, а затем говорит: «Хорошо, но делайте это в любом случае», я создам общее решение, в котором любое количество потоков по очереди передаёт токен от одного к другому через «BlockingQueues»: Когда поток получает токен, его очередь. Когда это будет сделано, он передает токен следующему потоку. –

ответ

1

Ваша проблема в том, что параметр вашего метода называется число тоже. Так что это тень поле вашего класса! Итак, когда вы опускаете, вы включаете параметр; который просто не имеет никакого реального эффекта!

Есть два пути решения этой проблемы:

а) просто избегать делать это (так, по соглашению избегать использования тех же имен параметров и полей).

b) Используйте инструменты, которые выявляют такие проблемы и рассказывают о них. Например, findbugs имеет явное указание rule, чтобы рассказать вам о затенении. И, вероятно, IDE можно предупредить об этом. См. here.

Учитывая тот факт, что это просто «просто» задание ... на мой взгляд, простая проверка на «пределе» общего класса будет просто отлично.

+0

Мне интересно, как я не заметил такую ​​маленькую вещь.Хорошо Спасибо за это. Не могли бы вы прокомментировать вторую часть вопроса. –

+0

«используйте инструменты, которые выявляют такие проблемы и рассказывают о том,« не могли бы вы рассказать об этом. Также, если другие варианты возможны для случая-2, пожалуйста, дайте мне знать. –

+0

Добавлены примеры таких инструментов. – GhostCat

Смежные вопросы