這篇文章將為大家詳細講解有關 JDK線程的基本協作機制wait和notify怎么用,文章內容質量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關知識有一定的了解。
線程間通信主要是通過wait、notify來實現的,使用這種機制實現線程通信是非常效率的,相比而言,不知道的同學針對線程通信可能只會想到輪詢的方式,下次可別再去輪詢共享變量了,把線程協作機制用起來。
首先,如果了解顯式鎖ReentrantLock或顯式條件Condition,我們就會知道鎖的隊列不止有一個等待隊列,還有一個等待條件隊列,存放等待被喚醒的線程。 對于用聲明式編程synchronized關鍵字來說,底層也是這種原理,對應的針對等待條件隊列入隊出隊方法就是鎖資源的wait/notify/notifyAll方法。但光有這種機制只能表示我們線程可以觸發其他線程繼續執行,前面說了叫等待條件隊列,那條件到底是什么勒?一般來說條件就是線程間共享的一個變量,這個變量用于控制線程等待或繼續執行??偨Y來說,notify一般伴隨著一個條件共享變量的改變,wait一般伴隨著一個條件共享變量的不滿足。比如如下代碼:
synchronized (this) { while (!condition) { wait(); } }
最開始condition不滿足,該線程放棄CPU執行權,進入等待條件隊列,然后等到其他線程做了其他事后,條件共享變量被改變,然后該線程被喚醒,然后繼續執行。
線程間的基本協作機制大致分為以下幾種:
生產者/消費者協作模式,生產者線程和消費者線程共享一個隊列變量,為了控制隊列的長度上限,當隊列為滿時,限制生產者線程等待,當添加信息到隊列時,隊列不為空,喚醒消費者隊列,當隊列為空時限制消費者線程等待,取到信息時,隊列不為滿,喚醒生產者隊列。
同時開始,所有子線程根據一個共享變量等待一個條件,同時開始的意思是主線程改變這個共享變量同時移除所有在等待條件隊列中的線程,如模擬仿真程序中,要求多個線程能同時開始。
等待結束,thread.join()方法的底層原理是while(子線程未結束){wait(0)},等待子線程結束。更好的方式實現是通過Java的CountDownLatch類來控制主線程的等待,子線程每結束一個線程計數器減1,主線程的等待條件是計數器為0,使用線程計數器也可以實現同時開始,只需要讓子線程共享線程計數器變量,等待條件是線程計數器為0,主線程將一個線程計數器傳入多個子線程并運行子線程,在一個時刻將線程計數器countDown為0就行了。這個主要是應用在主從協作模式中,主線程將任務分解為若干個子任務,為每個子任務創建一個線程,主線程在繼續執行其他任務之前需要等待每個子任務執行完畢。
異步結果,jdk并發包對異步任務進行了封裝,主要用于主從協作場景,如果不想手工創建線程,管理線程可以使用Excutors異步任務執行服務,核心是Future接口的get方法,該方法將等待異步任務返回執行結果,然后才會被喚醒并返回結果。
集合點,并發包中的CyclicBarrier柵欄就是這種場景的應用,一組子線程同時等待所有其他線程到一個地方之后再開始執行下面的邏輯,如一些并行計算場景,每個線程負責一部分計算,然后在集合點等待其他線程完成,所有線程到齊后,交換數據和計算結果,再進行下一次計算。
關于 JDK線程的基本協作機制wait和notify怎么用就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。