12.26 線程間通信

當多個線程可以一起工作去解決某個問題時,如果某些部分必須在其它部分之前完成,那麼就需要對線程進行協調。

wait/notify/notifyAll

  • wait - wait 方法使得線程釋放其佔有的對象鎖,讓線程從 Running 狀態轉入 Waiting 狀態,並等待 notify / notifyAll 來喚醒 。如果沒有釋放鎖,那麼其它線程就無法進入對象的同步方法或者同步控制塊中,那麼就無法執行 notify 或者 notifyAll 來喚醒掛起的線程,造成死鎖。
  • notify - 喚醒一個正在 Waiting 狀態的線程,並讓它拿到對象鎖,具體喚醒哪一個線程由 JVM 控制 。
  • notifyAll - 喚醒所有正在 Waiting 狀態的線程,接下來它們需要競爭對象鎖。


注意:

wait、notify、notifyAll 都是 Object 類中的方法,而非 Thread。

wait、notify、notifyAll 只能用在 synchronized 方法或者 synchronized 代碼塊中使用,否則會在運行時拋出 IllegalMonitorStateException。

為什麼 wait、notify、notifyAll 不定義在 Thread 中?為什麼 wait、notify、notifyAll 要配合 synchronized 使用?

首先,需要了解幾個基本知識點:

每一個 Java 對象都有一個與之對應的 監視器(monitor)

每一個監視器裡面都有一個 對象鎖 、一個 等待隊列、一個 同步隊列

瞭解了以上概念,我們回過頭來理解前面兩個問題。

為什麼這幾個方法不定義在 Thread 中?

由於每個對象都擁有對象鎖,讓當前線程等待某個對象鎖,自然應該基於這個對象(Object)來操作,而非使用當前線程(Thread)來操作。因為當前線程可能會等待多個線程的鎖,如果基於線程(Thread)來操作,就非常複雜了。

為什麼 wait、notify、notifyAll 要配合 synchronized 使用?

如果調用某個對象的 wait 方法,當前線程必須擁有這個對象的對象鎖,因此調用 wait 方法必須在 synchronized 方法和 synchronized 代碼塊中。


生產者、消費者模式是 wait、notify、notifyAll 的一個經典使用案例:

線程間通信


線程間通信

join

在線程操作中,可以使用 join 方法讓一個線程強制運行,線程強制運行期間,其他線程無法運行,必須等待此線程完成之後才可以繼續執行。

線程間通信

管道

管道輸入/輸出流和普通的文件輸入/輸出流或者網絡輸入/輸出流不同之處在於,它主要用於線程之間的數據傳輸,而傳輸的媒介為內存。 管道輸入/輸出流主要包括瞭如下 4 種具體實現:PipedOutputStream、PipedInputStream、PipedReader 和 PipedWriter,前兩種面向字節,而後兩種面向字符。

線程間通信

本皮是一個有著5年工作經驗的程序員,關於Java,自己有做材料的整合,一個完整學習Java的路線,學習材料和工具。需要的夥伴可以私信我,發送“交流”後就可免費獲取。對於學習Java有任何問題(學習方法,學習效率,如何就業)都可以問我。希望你也能憑自己的努力,成為下一個優秀的程序員!


分享到:


相關文章: