併發工具類(二)同步屏障CyclicBarrier

2021-09-11 15:38:18 字數 3521 閱讀 2623

前言

簡介cyclicbarrier 的字面意思是可迴圈使用(cyclic)的屏障(barrier)。它要做的事情是,讓一組執行緒到達乙個屏障(也可以叫同步點)時被阻塞,直到最後乙個執行緒到達屏障時,屏障才會開門,所有被屏障攔截的執行緒才會繼續幹活。cyclicbarrier預設的構造方法是cyclicbarrier(int parties),其引數表示屏障攔截的執行緒數量,每個執行緒呼叫await方法告訴cyclicbarrier我已經到達了屏障,然後當前執行緒被阻塞。

構造方法摘要

方法名稱

說明cyclicbarrier(int parties)

建立乙個新的 cyclicbarrier,它將在給定數量的參與者(執行緒)處於等待狀態時啟動,但它不會在啟動 barrier 時執行預定義的操作。

cyclicbarrier(int parties, runnable barrieraction)

建立乙個新的 cyclicbarrier,它將在給定數量的參與者(執行緒)處於等待狀態時啟動,並在啟動 barrier 時執行給定的屏障操作,該操作由最後乙個進入 barrier 的執行緒執行。

方法摘要

方法名稱

說明public int await() throws

interruptedexception, brokenbarrierexception

在所有參與者都已經在此 barrier 上呼叫 await 方法之前,將一直等待。

返回:

到達的當前執行緒的索引,其中,索引 getparties() - 1 指示將到達的第乙個執行緒,

零指示最後乙個到達的執行緒.

public int await(long timeout,timeunit unit) throws

interruptedexception,brokenbarrierexception,

itimeoutexception

在所有參與者都已經在此屏障上呼叫 await 方法之前將一直等待,或者超出了指定的等待時間。

public void reset()

將屏障重置為其初始狀態。如果所有參與者目前都在屏障處等待,則它們將返回,同時丟擲乙個 brokenbarrierexception。注意,在由於其他原因造成損壞之後,實行重置可能會變得很複雜;

public boolean isbroken()

查詢此屏障是否處於損壞狀態。

public int getnumberwaiting()

返回當前在屏障處等待的參與者數目。此方法主要用於除錯和斷言。

public int getparties()

返回要求啟動此 barrier 的參與者數目。

注意:

@ example1 屏障操作的例子

public

static

void

main

(string args)

});for(int i=0;i<5;i++)

}複製**

class

myrunable

implements

runnable

@override

public

void

run()

else

if(index == 0)else

} catch (interruptedexception | brokenbarrierexception e)

}}複製**

執行結果:

執行緒 thread_1 到達了屏障點!

執行緒 thread_4 到達了屏障點!

執行緒 thread_3 到達了屏障點!

執行緒 thread_0 到達了屏障點!

執行緒 thread_2 到達了屏障點!

執行緒thread_3執行了屏障操作

所有執行緒到達屏障點,執行緒 thread_3 被喚醒!!此執行緒是最後乙個到達屏障點

所有執行緒到達屏障點,執行緒 thread_0 被喚醒!!

所有執行緒到達屏障點,執行緒 thread_4 被喚醒!!

所有執行緒到達屏障點,執行緒 thread_1 被喚醒!!此執行緒是第乙個到達屏障點

所有執行緒到達屏障點,執行緒 thread_2 被喚醒!!

複製**

上面的例子,使用了傳入屏障操作的runable引數的構造方法,

屏障操作是由最後乙個到達屏障點的執行緒執行的,這是不可以改變的

。然而,在實際使用中,

可能會出現由第n個到達屏障點的執行緒執行特殊的操作(或者說 屏障操作),那麼就可以使用 cyclicbarrier.await()進行判斷

,如上面的例子,第乙個和最後乙個到達屏障點的執行緒都執行特殊的操作。

順便說一下,可能會對本例子中前5個輸出的順序 有所疑惑:thread_3 通過awiat()方法返回的索引值,可知 thread_3 是最後乙個到達屏障點的,但為什麼輸出的順序卻是第三個,而不是最後乙個;在這就要真正理解cyclicbarrier,cyclicbarrier 本質上是一把鎖,多個執行緒在使用cyclicbarrier 物件時,是需要先獲取鎖,即需要互斥訪問,所以呼叫await( )方法不一定能夠馬上獲取鎖。上面的例子,是先列印輸出,再去獲取鎖,所以輸出順序不是到達屏障點的順序。

@ example2 應用場景

下面的例子是:cyclicbarrier用於多執行緒計算資料,最後合併計算結果的場景。比如我們用乙個excel儲存了使用者所有銀行流水,每個sheet儲存乙個帳戶近一年的每筆銀行流水,現在需要統計使用者的日均銀行流水,先用多執行緒處理每個sheet裡的銀行流水,都執行完之後,得到每個sheet的日均銀行流水,最後,再用barrieraction用這些執行緒的計算結果,計算出整個excel的日均銀行流水。

public

class

bankwaterservice

implements

runnable

catch (interruptedexception | brokenbarrierexception e)

}});}}

@override

public

void

run()

sheetbankwatercount.put("result", result);

}public

static

void

main

(string args)

}複製**

執行結果:

執行緒pool-1-thread-4執行結束,最終的計算結果:4

執行緒pool-1-thread-2執行結束,最終的計算結果:4

執行緒pool-1-thread-1執行結束,最終的計算結果:4

執行緒pool-1-thread-3執行結束,最終的計算結果:4

複製**

cyclicbarrier和countdownlatch的區別

併發庫之同步屏障

讓一組執行緒達到乙個同步點時被阻塞,直到最後乙個執行緒達到同步點,這時候屏障才會放行,所有被屏障攔截的執行緒才會繼續執行。構造方法 public cyclicbarrier int parties public cyclicbarrier int parties runnable r 構造引數表示屏...

JAVA 併發程式設計 同步工具類

countdownlatch 閉鎖 閉鎖是一種同步工具類,可以延遲線程的進度知道其到達終止狀態。閉鎖的作用相當於一扇門 await 在閉鎖到達結束狀態之前,這扇門一直是關閉的,不允許任何執行緒通過,當到達結束狀態時 所有執行緒均到達countdown 這扇門會開啟並且允許所有的執行緒通過。而且,當門...

併發工具類

常用的閉鎖工具類 countdownlatch cyclicbarrier futuretask。閉鎖應用場景 1.有a b c三個執行緒一起執行,可是a執行緒需要等待b c執行緒任務執行完畢才繼續往下執行。2.乙個執行緒的某步計算依賴於其它執行緒的執行結果。用生活例子舉例,小明約小張和小李吃飯,小...