簡體   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