iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 5
2
Software Development

30 天介紹 Java 的 Thread系列 第 5

Day5:使用 Java Thread 的 wait、notify方法

在使用 Java Thread 開啟多執行的程式時,有時侯需要去等待其它的執行緒都執行完之後再啟動另外的執行緒,這時侯就可以使用 wait (等待) 和 notify (通知),二個互相搭配使用。

下面的例子來寫一個 sample code 在不使用 wait 和 notify 的情況下,從主程式開另外一個 thread 用來計算 1 加到 100,來看執行結果為何。Sample code 如下:

public class SumThread implements Runnable {
    int sum = 0;
    @Override
    public void run() {
        for (int i = 0 ; i <= 100 ; i++) {
            sum = sum + i;
        }
    }
}

上面的程式碼是在執行 thread 時,使用迴圈將 1 加到 100,然後會把累加的結放在 sum 變數裡。

public class Test {
    public static void main(String args[]) {
        SumThread sum = new SumThread();
        Thread thread = new Thread(sum);
        thread.start();
        int result = sum.sum;
        System.out.println("Count result is:" + result);
    }
}

在這裡的主程式會使用 SumThread 去啟動多執行結的程式,然後會把執行結果輸出,如下:

Count result is:0

我們會發現執行的結果是 0 ,這個計算結果是錯誤的。是因為在執行 Thread 時已經將結果先印出來之後,才完成 run 方法的計算 1 加到 100。因此造成執行的結果有問題。

要解這個問題就需要使用到 wait 和 notify,就是執行緒在還沒執行完之間 main 方法會先等待 (wait),等待執行緒執行完之後會通知 (notify) 執行完成了,這時侯輸出的執行結果才會是正確的。

修改完成的程式碼如下:

public class SumThread implements Runnable {
    int sum = 0;
    @Override
    public void run() {
        synchronized(this) {
          for (int i = 0 ; i <= 100 ; i++) {
            sum = sum + i;
          }
          notify();
        }
    }
}

以上 Thread 的程式如果執行完成就會發出通知 (notify) 執行完成了

public class Test {
    public static void main(String args[]) throws Exception{
        SumThread sum = new SumThread();
        Thread thread = new Thread(sum);
        thread.start();
        synchronized(thread) {
            thread.wait();
        }
        int result = sum.sum;
        System.out.println("Count result is:" + result);
    }
}

在主程式的部份會等待 (wait) Thread 執行完成之後,才會把結果印出來,執行結果如下:

Count result is:5050

這時輸出的結果才是正確的。因此如果在啟動執行緒時有考慮到執行順序的問題時,就可以使用 wait、notfiy 的方法。


上一篇
Day4:寫簡單 Java Thread Sample Code (二)
下一篇
Day6 執行緒安全的介紹
系列文
30 天介紹 Java 的 Thread30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中
2
Darwin Watterson
iT邦好手 1 級 ‧ 2018-10-19 09:06:59

幫你補充一個Java認證或面試常見考題:

Which are methods of the Object class? (Choose all that apply.)
✓ A. notify();
✓ B. notifyAll();
✗ C. isInterrupted();
✗ D. synchronized();
✗ E. interrupt();
✓ F. wait(1000L);
✗ G. sleep(1000L);
✗ H. yield()

謝謝啦!object class 的方法有 notify、notifyAll、wait。

JAVA API 網址如下:
https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html

0
wrxue
iT邦好手 1 級 ‧ 2020-06-12 17:12:42

請問wait與notify不是應該用在同一個物件上嗎,在SumThread裡的this應該指的是SumThread,跟主程式中的thread應該不是同一個物件。為什麼可以運作?

0
dididi
iT邦新手 5 級 ‧ 2021-04-13 11:37:05
public class **SumThread** implements **Runnable**

明明就是 Runnable 還寫成 Thread,看得我眼睛很花。害我看錯。
還以為可以 new Thread(thread) 爛死了。

然後程式還寫錯,根本不 work.
應該在 Runnable 裡面要寫 synchronized(thread) 而不是 synchronized(this)

我要留言

立即登入留言