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

print odd and even numbers using two threads in java efficiently?

我在一次采访中被问到下面的问题,我需要使用两个线程打印出偶数和奇数,所以我想出了下面的代码,但在这里我使用了两个 classes 一个实现 runnable接口和其他打印出使用 waitnotifyAll.

的数字
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 class,我可以在EvenOddTaskclass?

中直接打印不出来

您可以通过以下方式进行:

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

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

    这个class的main方法调用和上面的例子一样