简体   繁体   English

使用两个线程顺序打印奇偶数

[英]Printing Odd Even number sequentially using two threads

I am not able to understand why below program is not working in odd even scenario. 我不明白为什么下面的程序不能在偶数情况下工作。

Output I am getting is In Odd Thread 1 我得到的输出In Odd Thread 1

The program execution if I understand- 如果我理解程序执行-

Goes to t1 thread. 转到t1线程。 Condition not satisfied. 条件不满足。 Calls notifyAll which goes unnoticed.Goes to t2 thread, which prints odd number increments and calls wait(). 调用notifyAll,它会被忽略。转到t2线程,该线程输出奇数增量并调用wait()。 T2 should begin operation in this case right?? T2在这种情况下应该开始运行了吗??

public class OddEvenTest {

    static int max = 20;
    static int count = 1;
    static Object lock = new Object();

    public static void main(String[] args) {

        Thread t1 = new Thread(new Runnable() {

            @Override
            public void run() {
                synchronized (lock) {
                    while(count % 2  == 0 && count < max) {
                        System.out.println("In even Thread " +count);
                        count++;
                        try {
                            lock.wait();
                        } catch (InterruptedException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                    }

                    lock.notifyAll();
                }
            }
        });

        Thread t2 = new Thread(new Runnable() {

                    @Override
                    public void run() {
                        synchronized (lock) {
                            while(count % 2  != 0 && count < max) {
                                System.out.println("In Odd Thread " +count);
                                count++;
                                try {
                                    lock.wait();
                                } catch (InterruptedException e) {
                                    // TODO Auto-generated catch block
                                    e.printStackTrace();
                                }               
                            }
                            lock.notifyAll();
                        }

                    }
                });

        t1.start();
        t2.start();

    }

}

You don't want to blindly wait() in a loop synchronized on your lock . 您不想盲目地在lock同步的循环中使用wait() Instead, check your pre-conditions for wait ing, like 相反,请检查您的wait条件,例如

Thread t1 = new Thread(new Runnable() {
    @Override
    public void run() {
        while (count < max) {
            synchronized (lock) {
                if (count % 2 == 0) {
                    System.out.println("In Even Thread " + count);
                    count++;
                    lock.notifyAll();
                } else {
                    try {
                        lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
});

Thread t2 = new Thread(new Runnable() {
    @Override
    public void run() {
        while (count < max) {
            synchronized (lock) {
                if (count % 2 != 0) {
                    System.out.println("In Odd Thread " + count);
                    count++;
                    lock.notifyAll();
                } else {
                    try {
                        lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
});

In Java 8+, you can simplify your anonymous classes with lambdas like 在Java 8+中,您可以使用以下lambda简化匿名类

Thread t1 = new Thread(() -> {
    while (count < max) {
        synchronized (lock) {
            if (count % 2 == 0) {
                System.out.println("In Even Thread " + count);
                count++;
                lock.notifyAll();
            } else {
                try {
                    lock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
});

Thread t2 = new Thread(() -> {
    while (count < max) {
        synchronized (lock) {
            if (count % 2 != 0) {
                System.out.println("In Odd Thread " + count);
                count++;
                lock.notifyAll();
            } else {
                try {
                    lock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
});

There are many problems i can think of 我能想到很多问题

  1. notifyAll has been written outside the loop so think about a scenario where odd thread is getting executed and printed the value and it is about to call wait but even thread has called notify before odd thread call wait so odd thread will always be in waiting state. notifyAll已写在循环外,因此请考虑以下情况:奇数线程正在执行并打印该值,并且即将调用wait,但是偶数线程在奇数线程调用等待之前调用了notify,因此奇数线程将始终处于等待状态。 So you should keep notifyAll inside loop. 因此,您应该在循环内保持notifyAll。
    This is something you have experienced in your execution. 这是您在执行过程中所经历的。

  2. while loop should keep executing till count is less than max and the even or condition should be applied inside while loop. while循环应继续执行,直到count小于最大数为止,并且应在while循环内部应用偶数或条件。

  3. wait should go in else condition 等待应该在其他情况下

Refactored Code 重构代码

public class OddEvenTest {

  static int max = 20;
  static int count = 1;
  static Object lock = new Object();

  public static void main(String[] args) {

    Thread t1 = new Thread(new Runnable() {

      @Override
      public void run() {
        synchronized (lock) {
          while(count < max) {
            if(count % 2  == 0 ) {
              System.out.println("In even Thread " + count);
              count++;
            }else{
              try {
                lock.wait();
              } catch (InterruptedException e) {
                System.out.println(e.getMessage());
                e.printStackTrace();
              }
            }
            lock.notifyAll();
          }
        }
      }
    });

    Thread t2 = new Thread(new Runnable() {

      @Override
      public void run() {
        synchronized (lock) {
          while(count < max) {
            if(count % 2  != 0) {
              System.out.println("In Odd Thread " + count);
              count++;
            }else{
              try {
                lock.wait();
              } catch (InterruptedException e) {
                e.printStackTrace();
                System.out.println(e.getMessage());
              }
            }
            lock.notifyAll();
          }
        }

      }
    });

    t1.start();
    t2.start();

  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM