天天看點

Java并發新構件之CounDownLatch

    countdownlatch主要用于同步一個或多個任務,強制它們等待由其他任務執行的一組操作完成。

    你可以向countdownlatch對象設定一個初始計數值,任何在這個對象上調用wait()的方法都将阻塞,直到這個計數值達到0.其他任務在結束其工作時,可以在該對象上調用countdown()來減小這個計數值,你可以通過調用getcount()方法來擷取目前的計數值。countdownlatch被設計為隻觸發一次,計數值不能被重置。如果你需要能夠重置計數值的版本,則可以使用cyclicbarrier。

    調用countdown()的任務在産生這個調用時并沒有阻塞,隻有對await()的調用會被阻塞,直到計數值到達0。

    countdownlatch的典型用法是将一個程式分為n個互相獨立的可解決人物,并建立值為0的countdownlatch。當每個任務完成是,都會在這個鎖存器上調用countdown()。等待問題被解決的任務在這個鎖存器上調用await(),将它們自己鎖住,直到鎖存器計數結束。下面是示範這種技術的一個架構示例:

<a href="http://my.oschina.net/itblog/blog/516282#">?</a>

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

<code>import</code> <code>java.util.random;</code>

<code>import</code> <code>java.util.concurrent.countdownlatch;</code>

<code>import</code> <code>java.util.concurrent.delayqueue;</code>

<code>import</code> <code>java.util.concurrent.executorservice;</code>

<code>import</code> <code>java.util.concurrent.executors;</code>

<code>import</code> <code>java.util.concurrent.timeunit;</code>

<code>class</code> <code>taskportion </code><code>implements</code> <code>runnable {</code>

<code>    </code><code>private</code> <code>static</code> <code>int</code> <code>counter = </code><code>0</code><code>;</code>

<code>    </code><code>private</code> <code>final</code> <code>int</code> <code>id = counter++;</code>

<code>    </code><code>private</code> <code>static</code> <code>random random = </code><code>new</code> <code>random();</code>

<code>    </code><code>private</code> <code>final</code> <code>countdownlatch latch;</code>

<code>    </code><code>public</code> <code>taskportion(countdownlatch latch) {</code>

<code>        </code><code>this</code><code>.latch = latch;</code>

<code>    </code><code>}</code>

<code>    </code><code>@override</code>

<code>    </code><code>public</code> <code>void</code> <code>run() {</code>

<code>        </code><code>try</code> <code>{</code>

<code>            </code><code>dowork();</code>

<code>            </code><code>latch.countdown();</code><code>//普通任務執行完後,調用countdown()方法,減少count的值</code>

<code>            </code><code>system.out.println(</code><code>this</code> <code>+ </code><code>" completed. count="</code> <code>+ latch.getcount());</code>

<code>        </code><code>} </code><code>catch</code> <code>(interruptedexception e) {</code>

<code>            </code> 

<code>        </code><code>}</code>

<code>    </code> 

<code>    </code><code>public</code> <code>void</code> <code>dowork() </code><code>throws</code> <code>interruptedexception {</code>

<code>        </code><code>timeunit.milliseconds.sleep(random.nextint(</code><code>2000</code><code>));</code>

<code>    </code><code>public</code> <code>string tostring() {</code>

<code>        </code><code>return</code> <code>string.format(</code><code>"%1$-2d "</code><code>, id);</code>

<code>}</code>

<code>class</code> <code>waitingtask </code><code>implements</code> <code>runnable {</code>

<code>    </code><code>public</code> <code>waitingtask(countdownlatch latch) {</code>

<code>            </code><code>//這些後續任務需要等到之前的任務都執行完成後才能執行,即count=0時</code>

<code>            </code><code>latch.await();</code>

<code>            </code><code>system.out.println(</code><code>"latch barrier passed for "</code> <code>+ </code><code>this</code><code>);</code>

<code>            </code><code>system.out.println(</code><code>this</code> <code>+ </code><code>" interrupted."</code><code>);</code>

<code>        </code><code>return</code> <code>string.format(</code><code>"waitingtask %1$-2d "</code><code>, id);</code>

<code>public</code> <code>class</code> <code>countdownlatchdemo {</code>

<code>    </code><code>static</code> <code>final</code> <code>int</code> <code>size = </code><code>10</code><code>;</code>

<code>    </code><code>public</code> <code>static</code> <code>void</code> <code>main(string[] args) {</code>

<code>        </code><code>countdownlatch latch = </code><code>new</code> <code>countdownlatch(size);</code>

<code>        </code><code>executorservice exec = executors.newcachedthreadpool();</code>

<code>        </code><code>//10個waitingtask</code>

<code>        </code><code>for</code> <code>(</code><code>int</code> <code>i = </code><code>0</code><code>; i &lt; </code><code>5</code><code>; i++) {</code>

<code>            </code><code>exec.execute(</code><code>new</code> <code>waitingtask(latch));</code>

<code>        </code><code>//100個任務,這100個任務要先執行才會執行waitingtask</code>

<code>        </code><code>for</code> <code>(</code><code>int</code> <code>i = </code><code>0</code><code>; i &lt; size; i++) {</code>

<code>            </code><code>exec.execute(</code><code>new</code> <code>taskportion(latch));</code>

<code>        </code><code>system.out.println(</code><code>"launched all tasks."</code><code>);</code>

<code>        </code><code>exec.shutdown();</code><code>//當所有的任務都結束時,關閉exec</code>

執行結果(可能的結果):

<code>launched all tasks.</code>

<code>4</code>   <code>completed. count=</code><code>9</code>

<code>6</code>   <code>completed. count=</code><code>8</code>

<code>3</code>   <code>completed. count=</code><code>7</code>

<code>0</code>   <code>completed. count=</code><code>6</code>

<code>2</code>   <code>completed. count=</code><code>5</code>

<code>1</code>   <code>completed. count=</code><code>4</code>

<code>5</code>   <code>completed. count=</code><code>3</code>

<code>7</code>   <code>completed. count=</code><code>2</code>

<code>9</code>   <code>completed. count=</code><code>1</code>

<code>8</code>   <code>completed. count=</code><code>0</code>

<code>latch barrier passed </code><code>for</code> <code>waitingtask </code><code>0</code>  

<code>latch barrier passed </code><code>for</code> <code>waitingtask </code><code>2</code>  

<code>latch barrier passed </code><code>for</code> <code>waitingtask </code><code>1</code>  

<code>latch barrier passed </code><code>for</code> <code>waitingtask </code><code>3</code>  

<code>latch barrier passed </code><code>for</code> <code>waitingtask </code><code>4</code>

    從結果中可以看到,所有的waitingtask都是在所有的taskportion執行完成之後執行的。

    taskportion将随機的休眠一段時間,以模拟這部分工作的完成。而waitingtask表示系統中必須等待的部分,它要等到問題的初始部分完成後才能執行。注意:所有任務都使用了在main()中定義的同一個countdownlatch對象。