Java多執行緒之執行緒間通訊詳解
下面小編就為大家帶來一篇java多執行緒程式設計學習(線程間通訊)。小編覺得蠻不錯的,現在就分享給大家,也給大家做個參考。一起跟著小編過來看看吧
一、概要
#線程是作業系統中獨立的個體,但這些個體若不經過特殊的處理就不能成為一個整體,線程間的通訊就是成為整體的必用方案之一。可以說,使執行緒進行通訊後,系統之間的互動性會更強大,在大幅提高cpu利用率的同時也會使程式設計師對各執行緒任務在處理過程中進行有效的把控和監督。
二、等待/通知機制
1、"wait/notify"機制:等待/通知機制, wait使執行緒暫停運行,而notify 使暫停的執行緒繼續運行。用一個廚師和服務生的互動來說明:
(1) 服務生取到菜的時間取決於廚師,所以服務生就有「等待」(wait)的狀態。
(2) 廚師將菜放在「菜品傳遞台」上,其實就相當於一種通知(notify),這時服務員才可以拿到菜並交給就餐者。
2、wait()
(1) 使目前執行程式碼的執行緒進行等待。 wait()方法是Object類別的方法,該方法用來將目前執行緒置入「預執行佇列」中,並且在wait()所在的程式碼行處停止執行,直到接收通知或中斷為止。
(2) 在呼叫wait()方法之前,執行緒必須取得該物件的物件級鎖,即只能在同步方法或同步區塊中呼叫wait()方法,否則拋出IllegalMonitorStateException例外。 (屬於Runtime的子類,不需要try-catch 語句進行捕捉異常)
(3) 在呼叫wait()方法之後,當前執行緒釋放鎖,而此物件會進入執行緒等待池中,等待被喚醒。在從wait()返回前,線程與其他呈wait線程競爭重新獲得鎖。
(4) wait()方法可以被interrupt 打斷並拋出InterruptedException。
(5) wait(long):帶一個參數的wait(long)方法的功能是等待某一時間內是否有執行緒對鎖進行喚醒,如果超過這個時間則自動喚醒。
3、notify()
(1) 用來通知那些可能等待該物件的物件鎖的其他執行緒。如果有多個線程等待,則由線程規劃器隨機挑選出其中一個呈wait狀態的線程,對其發出通知notify,並使它等待獲取該物件的物件鎖。 (注意!這裡說的是等待,即在執行完notify()方法後,當前線程不會馬上釋放該物件鎖,即wait()狀態的線程也不會馬上獲得物件鎖,需要將synchronized 程式碼區塊中的程式碼執行完後才釋放鎖定!鎖,否則也會拋出IllegalMonitorStateException.
(3)當notify()發出通知,卻沒有wait()執行緒在等待時,則不作作用。
4、notifyAll()(1) 可以使所有正在等待隊列中的等待同一共享資源(即同一個鎖) 的"全部"線程從等待狀態退出,進入可運作狀態。
5、
假死:「假死「現像其實就是線程進入WAITING等待狀態。如果全部執行緒都進入WAITING狀態,程式就不再執行任何功能了,整個專案呈現停止狀態。 出現這樣的原因是因為:例如多個生產者和多個消費者的問題,“生產者”可能喚醒“生產者”,“消費者”可能喚醒“消費者”,喚醒了同類,導致線程不斷在等待。怎麼解決這個問題呢?將notify() 改成 notifyAll()方法即可,也就是將異類一同喚醒就可以了。
7、Jave中 管道流(pipeStream)是一種特殊的流,可用來在不同的執行緒中直接傳送資料。一個執行緒發送資料到輸出管道,另一個執行緒從輸入管道中讀取資料。透過使用管道,實現不同線程間的通信,而無須借助於類似臨時文件之類的東西。 JDK中提供了四個類別來使線程間可以通信,其中包括位元組流(PipedOutputStream、PipedInputStream)和字元流(PipedWriter、PipedReader)。
#
public class Run { public static void main(String[] args) { try { WriteData writeData = new WriteData(); ReadData readData = new ReadData(); PipedOutputStream outputStream = new PipedOutputStream(); PipedInputStream inputStream = new PipedInputStream(); outputStream.connect(inputStream);//使两个Stream之间产生通信链接,这样才可以将数据进行输入输出 ThreadRead threadRead = new ThreadRead(readData, inputStream); threadRead.start(); Thread.sleep(1000); ThreadWrite threadWrite = new ThreadWrite(writeData, outputStream); threadWrite.start(); } catch (IOException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } } }
三、方法join的使用 1、在很多情況下,主線程創建並啟動子線程,如果子線程中要進行大量的耗時計算,主線程往往將早於子線程結束之前結束。這時,如果主執行緒想等待子執行緒執行完成之後再結束,例如子執行緒處理一個數據,主執行緒要取得這個數據中的值,就要用到join()方法了。 2、join()的作用是等待執行緒銷毀,而使 當前執行緒進行無限期的阻塞,等待join()的執行緒銷毀後再繼續執行目前執行緒的程式碼。 3、同樣的,join()方法可以被interrupt()方法打斷並拋出InterruptedException異常。 4、join 與 synchronized 的差別? (1) join()在內部使用wait() 方法進行等待。 (2) synchronized 關鍵字使用的是「物件監視器」原理作為同步。 5、方法join(long) 和 sleep(long)的差別? (1) join(long)內部採用wait(long)方法實現,當執行wait(long)方法後,當前執行緒的鎖被釋放,那麼其他執行緒也可以呼叫此執行緒中的同步方法了。即 join(long)之後,該執行緒釋放鎖,又需要和其他執行緒去爭搶鎖的資源。 (2) Thread.sleep(long)方法不釋放鎖定。 四、類別ThreadLocal 的使用 #1、變數值的共用可以使用public static 變數的形式,所有的線程都使用同一個public static 變數。如果想實現每一個執行緒都有自己的共享變數該如何解決呢?類別ThreadLocal解決的是每個執行緒綁定自己的值,可以將ThreadLocal類別比喻為全域存放資料的盒子,盒子中可以存放每個執行緒的私有資料。 2、類別ThreadLocal 具有隔離性,也就是每個執行緒都可以存入自己執行緒的資料而互不影響,而取到的也是自己執行緒存入的資料。 #五、類別InheritableThreadLocal的使用 ##1、InheritableThreadLocal類別繼承於ThreadLocal類,所以它具有ThreadLocal類別的特性,但又是一個特殊的ThreadLocal,其特殊性在於InheritableThreadLocal變數值會自動傳遞給所有子執行緒,而普通ThreadLocal變數不行;而且,透過重寫這個類別中的 childValue 方法,子執行緒的值可以當父線程值的一個任意函數。 備註: (1) 什麼是子執行緒? 包含在 Thread thread = new Thread(new ThreadStart(delegate{ (2) 什麼是主執行緒? UI介面和Main函數皆為主線程,除了「不包含在Thread裡面的程式」皆可 視為主執行緒。 (個人理解)
}));裡面皆視為子執行緒。 (個人理解)
以上是Java多執行緒之執行緒間通訊詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

Java 8引入了Stream API,提供了一種強大且表達力豐富的處理數據集合的方式。然而,使用Stream時,一個常見問題是:如何從forEach操作中中斷或返回? 傳統循環允許提前中斷或返回,但Stream的forEach方法並不直接支持這種方式。本文將解釋原因,並探討在Stream處理系統中實現提前終止的替代方法。 延伸閱讀: Java Stream API改進 理解Stream forEach forEach方法是一個終端操作,它對Stream中的每個元素執行一個操作。它的設計意圖是處

PHP是一種廣泛應用於服務器端的腳本語言,特別適合web開發。 1.PHP可以嵌入HTML,處理HTTP請求和響應,支持多種數據庫。 2.PHP用於生成動態網頁內容,處理表單數據,訪問數據庫等,具有強大的社區支持和開源資源。 3.PHP是解釋型語言,執行過程包括詞法分析、語法分析、編譯和執行。 4.PHP可以與MySQL結合用於用戶註冊系統等高級應用。 5.調試PHP時,可使用error_reporting()和var_dump()等函數。 6.優化PHP代碼可通過緩存機制、優化數據庫查詢和使用內置函數。 7

膠囊是一種三維幾何圖形,由一個圓柱體和兩端各一個半球體組成。膠囊的體積可以通過將圓柱體的體積和兩端半球體的體積相加來計算。本教程將討論如何使用不同的方法在Java中計算給定膠囊的體積。 膠囊體積公式 膠囊體積的公式如下: 膠囊體積 = 圓柱體體積 兩個半球體體積 其中, r: 半球體的半徑。 h: 圓柱體的高度(不包括半球體)。 例子 1 輸入 半徑 = 5 單位 高度 = 10 單位 輸出 體積 = 1570.8 立方單位 解釋 使用公式計算體積: 體積 = π × r2 × h (4

PHP和Python各有優勢,選擇應基於項目需求。 1.PHP適合web開發,語法簡單,執行效率高。 2.Python適用於數據科學和機器學習,語法簡潔,庫豐富。

Java是熱門程式語言,適合初學者和經驗豐富的開發者學習。本教學從基礎概念出發,逐步深入解說進階主題。安裝Java開發工具包後,可透過建立簡單的「Hello,World!」程式來實踐程式設計。理解程式碼後,使用命令提示字元編譯並執行程序,控制台上將輸出「Hello,World!」。學習Java開啟了程式設計之旅,隨著掌握程度加深,可創建更複雜的應用程式。

Spring Boot簡化了可靠,可擴展和生產就緒的Java應用的創建,從而徹底改變了Java開發。 它的“慣例慣例”方法(春季生態系統固有的慣例),最小化手動設置
