繁体   English   中英

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

[英]Printing Odd Even number sequentially using two threads

我不明白为什么下面的程序不能在偶数情况下工作。

我得到的输出In Odd Thread 1

如果我理解程序执行-

转到t1线程。 条件不满足。 调用notifyAll,它会被忽略。转到t2线程,该线程输出奇数增量并调用wait()。 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();

    }

}

您不想盲目地在lock同步的循环中使用wait() 相反,请检查您的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();
                    }
                }
            }
        }
    }
});

在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();
                }
            }
        }
    }
});

我能想到很多问题

  1. notifyAll已写在循环外,因此请考虑以下情况:奇数线程正在执行并打印该值,并且即将调用wait,但是偶数线程在奇数线程调用等待之前调用了notify,因此奇数线程将始终处于等待状态。 因此,您应该在循环内保持notifyAll。
    这是您在执行过程中所经历的。

  2. while循环应继续执行,直到count小于最大数为止,并且应在while循环内部应用偶数或条件。

  3. 等待应该在其他情况下

重构代码

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