печатать нечетные и четные числа, используя два потока в Java эффективно? - PullRequest
0 голосов
/ 12 октября 2018

Мне задали следующий вопрос в интервью, где мне нужно распечатать четные и нечетные числа, используя два потока, поэтому я пришел с кодом ниже, но в этом я использую два класса, один из которых реализует работающий интерфейс, а другой - для распечатки.число, которое использует wait и notifyAll.

public class PrintEvenOddTester {

  public static void main(String[] args) {
    Output print = new Output();
    Thread t1 = new Thread(new EvenOddTask(print, 10, false));
    Thread t2 = new Thread(new EvenOddTask(print, 10, true));
    t1.start();
    t2.start();
  }
}


class EvenOddTask implements Runnable {
  private int max;
  private Output print;
  private boolean isEvenNumber;

  EvenOddTask(Output print, int max, boolean isEvenNumber) {
    this.print = print;
    this.max = max;
    this.isEvenNumber = isEvenNumber;
  }

  @Override
  public void run() {
    int number = isEvenNumber == true ? 2 : 1;
    while (number <= max) {
      if (isEvenNumber) {
        print.printEven(number);
      } else {
        print.printOdd(number);
      }
      number += 2;
    }
  }
}


class Output {
  boolean isOdd = false;

  public synchronized void printEven(int number) {
    while (isOdd == false) {
      try {
        wait();
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
    System.out.println("Even:" + number);
    isOdd = false;
    notifyAll();
  }

  public synchronized void printOdd(int number) {
    while (isOdd == true) {
      try {
        wait();
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
    System.out.println("Odd:" + number);
    isOdd = true;
    notifyAll();
  }
}

Я хотел проверить, существует ли какой-либо лучший или простой способ выполнения подобных задач в Java 7. В общем случае вместо использования другого Output класс, я не могу распечатать непосредственно в EvenOddTask классе?

1 Ответ

0 голосов
/ 12 октября 2018

Вы можете сделать это следующими способами:

  1. Без использования синхронизации:

    class Print {
    
        private static int count = 1;
        private static int MAX = 20;
        private boolean isOdd = true;
    
        public void printEven() {
            while (true) {
                if (count > MAX) break;
                if (!isOdd) {
                    System.err.println(Thread.currentThread().getName() + ":" + count++);
                    isOdd = true;
                }
            }
        }
    
        public void printOdd() {
            while (true) {
                if (count > MAX) break;
                if (isOdd) {
                    System.err.println(Thread.currentThread().getName() + ":" + count++);
                    isOdd = false;
                }
            }
        }
    
    }
    
    public class ThreadOddEven {
        public static void main(String[] args) {
            Print p = new Print();
    
            // Thread t1 = new Thread(() -> p.printEven());
            Thread t1 = new Thread(new Runnable() {     
               @Override
               public void run() {
                  p.printEven();                
               }
            });
            t1.setName("EVEN");
    
            // Thread t2 = new Thread(() -> p.printOdd());
            Thread t2 = new Thread(new Runnable() {
               @Override
               public void run() {
                  p.printOdd(); 
               }
            });
            t2.setName("ODD");
    
            t1.start();
            t2.start();
        }
    
    }
    

    Это, пожалуй, самый простой способчтобы добиться печати нечетных и четных чисел в двух потоках.

    Здесь мы просто используем логическую переменную isOdd.Это значение переключается после того, как каждый поток выводит значение.

  2. Использование синхронизации:

    class Print2 {
    
        private static int count = 1;
        private static int MAX = 10;
        private Object obj = new Object();
    
        public void printEven() {
            while (true) {
                if (count > MAX) break;
                synchronized (obj) {
                    System.err.println(Thread.currentThread().getName() + " : " + count++);
                    obj.notify();
                    try {
                        obj.wait();
                    } catch (InterruptedException e) { }
                }
            }
        }
    
        public void printOdd() {
            while (true) {
                if (count > MAX) break;
                synchronized (obj) {
                    System.err.println(Thread.currentThread().getName() + " : " + count++);
                    obj.notify();
                    try {
                        obj.wait();
                    } catch (InterruptedException e) { }
                }
            }
        }
    
    }
    

    Во втором примере вместо использования логического значенияпеременная, мы используем объект, чтобы мы могли синхронизировать вызовы между двумя потоками.

    Основной вызов метода для этого класса такой же, как в приведенном выше примере.

...