代码之家  ›  专栏  ›  技术社区  ›  flash

在java中使用两个线程高效地打印奇偶数?

  •  1
  • flash  · 技术社区  · 6 年前

    我被问到下面的问题,在一次采访中,我需要打印出偶数和奇数使用两个线程,所以我想出了下面的代码,但在这我使用两个类一个实现runnable接口,另一个打印出的数字使用 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();
      }
    }
    

    我想看看在Java7中是否有更好或更简单的方法来完成这类任务 Output EvenOddTask 上课?

    1 回复  |  直到 6 年前
        1
  •  1
  •   Nicholas K    6 年前

    您可以通过以下方式执行此操作:

    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) { }
                  }
              }
          }
      
      }
      

      在第二个示例中,我们没有使用布尔变量,而是 使用一个对象以便我们可以在两个对象之间同步调用 线程。