Java高性能編程實戰 - 線程通訊

要想實現多個線程之間的協同,如:線程執行前後順序、獲取某個線程執行的結果等等。涉及到線程之間相互通訊,分爲下面四類:編程

1 文件共享

2 網絡共享

socket編程問題,非本文重點,再也不贅述api

3 共享變量

4 線程協做 - JDK API

細分爲: suspend/resume 、 wait/notify、 park/unpark網絡

JDK中對於須要多線程協做完成某一任務的場景,提供了對應API支持。多線程協做的典型場景是:生產者-消費者模型。(線程阻塞、 線程喚醒)多線程

示例:線程1去買包子,沒有包子,則再也不執行。線程-2生產出包子,通知線程-1繼續執行。socket

4.1 API - 被棄用的suspend和resume

做用:調用suspend掛起目標線程,經過resume能夠恢復線程執行工具

被棄用的主要緣由是,容易寫出開發工具

死鎖代碼

  • 同步代碼中使用

  • 前後順序:suspend比resume後執行

因此用wait/notify和park/unpark機制對它進行替代線程

4.2 wait/notify

這些方法只能由同一對象鎖的持有者線程調用,也就是寫在同步塊裏面,不然會拋IllegalMonitorStateException3d

wait 方法致使當前線程等待,加入該對象的等待集合中,而且放棄當前持有的對象鎖code

notify/notifyAll 方法喚醒一個 或全部正在等待這個對象鎖的線程。

雖然wait會自動解鎖,可是對順序有要求,若是在notify被調用以後, 纔開始wait方法的調用,線程會永遠處於WAITING狀態。

  • 正常使用
  • 死鎖

  • 小結

4.3 park/unpark

線程調用park則等待「許可」,unpark方法爲指定線程提供「許可(permit)」 。

不要求park和unpark方法的調用順序

屢次調用unpark以後,再調用park, 線程會直接運行。但不會疊加,即連續屢次調用park方法,第一次會拿到「許可」直接運行,後續調用會進入等待。

  • 正常
  • 死鎖

5 僞喚醒

以前代碼中用if語句來判斷,是否進入等待狀態,是錯誤的!

官方建議應該在循環中檢查等待條件,緣由是處於等待狀態的線程可能會收到**錯誤警報和僞喚醒**,若是不在循環中檢查等待條件,程序就會在沒有知足結束條件的狀況下退出。

僞喚醒是指線程並不是由於notify、notifyall、 unpark等 api調用而喚醒,是更底層緣由致使的。

6 總結

涉及不少JDK多線程開發工具類及其底層實現的原理

相關文章
相關標籤/搜索