天天看點

線程同步工具(三)等待多個并發事件完成

java并發api提供這樣的類,它允許1個或者多個線程一直等待,直到一組操作執行完成。 這個類就是countdownlatch類。它初始一個整數值,此值是線程将要等待的操作數。當某個線程為了想要執行這些操作而等待時, 它要使用 await()方法。此方法讓線程進入休眠直到操作完成。 當某個操作結束,它使用countdown() 方法來減少countdownlatch類的内部計數器。當計數器到達0時,這個類會喚醒全部使用await() 方法休眠的線程們。

在這個指南,你将學習如果使用 countdownlatch 類來實作 video- conference 系統。 video-conference 系統将等待全部參與者到達後才會開始。

準備

指南中的例子是使用eclipse ide 來實作的。如果你使用eclipse 或者其他的ide,例如netbeans,打開并建立一個新的java任務。

怎麼做呢<b>…</b>

按照這些步驟來實作下面的例子::

<code>01</code>

<code>//1.   建立一個類名為 videoconference 并特别實作 runnable 接口。這個類将實作 video-conference 系統。</code>

<code>02</code>

<code>public</code> <code>class</code> <code>videoconference </code><code>implements</code> <code>runnable{</code>

<code>03</code>

<code>04</code>

<code>//2.   聲明 countdownlatch 對象名為 controller。</code>

<code>05</code>

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

<code>06</code>

<code>07</code>

<code>//3.   實作類的構造函數,初始 countdownlatch 屬性。videoconference 類接收将要等待的參與者的量為參數。</code>

<code>08</code>

<code>public</code> <code>videoconference(</code><code>int</code> <code>number) {</code>

<code>09</code>

<code>    </code><code>controller=</code><code>new</code> <code>countdownlatch(number);</code>

<code>10</code>

<code>}</code>

<code>11</code>

<code>12</code>

<code>//4.   實作 arrive() 方法。每次有參與者到達都會調用此方法。它接收string類型的參數名為 name。</code>

<code>13</code>

<code>public</code> <code>void</code> <code>arrive(string name){</code>

<code>14</code>

<code>15</code>

<code>//5.   首先,它輸出某某參數已經到達。</code>

<code>16</code>

<code>system.out.printf(&amp;quot;%s has arrived.&amp;quot;,name);</code>

<code>17</code>

<code>18</code>

<code>//6.   然後,調用countdownlatch對象的 countdown() 方法。</code>

<code>19</code>

<code>controller.countdown();</code>

<code>20</code>

<code>21</code>

<code>//7.    最後,使用countdownlatch對象的 getcount() 方法輸出另一條關于還未确定到達的參與者數。</code>

<code>22</code>

<code>system.out.printf(&amp;quot;videoconference: waiting </code><code>for</code> <code>%d participants.\n&amp;quot;,controller.getcount());</code>

<code>23</code>

<code>24</code>

<code>//8.   實作video-conference 系統的主方法。它是每個runnable都必須有的 run() 方法。</code>

<code>25</code>

<code>@override</code>

<code>26</code>

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

<code>27</code>

<code>28</code>

<code>//9.   首先,使用 getcount() 方法來輸出這次video conference的參與值的數量資訊。</code>

<code>29</code>

<code>system.out.printf(&amp;quot;videoconference: initialization: %d participants.\n&amp;quot;,controller.getcount());</code>

<code>30</code>

<code>31</code>

<code>//10. 然後, 使用 await() 方法來等待全部的參與者。由于此法會抛出 interruptedexception 異常,是以要包含處理代碼。</code>

<code>32</code>

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

<code>33</code>

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

<code>34</code>

<code>35</code>

<code>//11. 最後,輸出資訊表明全部參與者已經到達。</code>

<code>36</code>

<code>system.out.printf(&amp;quot;videoconference: all the participants have come\n&amp;quot;);</code>

<code>37</code>

<code>system.out.printf(&amp;quot;videoconference: let's start...\n&amp;quot;);</code>

<code>38</code>

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

<code>39</code>

<code>    </code><code>e.printstacktrace();</code>

<code>40</code>

<code>41</code>

<code>42</code>

<code>//12. 建立 participant 類并實作 runnable 接口。這個類表示每個video conference的參與者。</code>

<code>43</code>

<code>public</code> <code>class</code> <code>participant </code><code>implements</code> <code>runnable {</code>

<code>44</code>

<code>45</code>

<code>//13. 聲明一個私有 videoconference 屬性名為 conference.</code>

<code>46</code>

<code>private</code> <code>videoconference conference;</code>

<code>47</code>

<code>48</code>

<code>//14. 聲明一個私有 string 屬性名為 name。</code>

<code>49</code>

<code>private</code> <code>string name;</code>

<code>50</code>

<code>51</code>

<code>//15. 實作類的構造函數,初始化那2個屬性。</code>

<code>52</code>

<code>public</code> <code>participant(videoconference conference, string name) {</code>

<code>53</code>

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

<code>54</code>

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

<code>55</code>

<code>56</code>

<code>57</code>

<code>//16. 實作參與者的run() 方法。</code>

<code>58</code>

<code>59</code>

<code>60</code>

<code>61</code>

<code>//17.  首先,讓線程随機休眠一段時間。</code>

<code>62</code>

<code>long</code> <code>duration=(</code><code>long</code><code>)(math.random()*</code><code>10</code><code>);</code>

<code>63</code>

<code>64</code>

<code>    </code><code>timeunit.seconds.sleep(duration);</code>

<code>65</code>

<code>66</code>

<code>67</code>

<code>68</code>

<code>69</code>

<code>//18. 然後,使用videoconference 對象的arrive() 方法來表明參與者的到達。</code>

<code>70</code>

<code>conference.arrive(name);</code>

<code>71</code>

<code>72</code>

<code>//19. 最後,實作例子的 main 類通過建立一個名為 main 的類并為其添加 main() 方法。</code>

<code>73</code>

<code>public</code> <code>class</code> <code>main {</code>

<code>74</code>

<code>75</code>

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

<code>76</code>

<code>77</code>

<code>//20. 建立 videoconference 對象名為 conference,将等待10個參與者。</code>

<code>78</code>

<code>videoconference conference=</code><code>new</code> <code>videoconference(</code><code>10</code><code>);</code>

<code>79</code>

<code>80</code>

<code>//21. 建立 thread 來運作這個 videoconference 對象并開始運作。</code>

<code>81</code>

<code>thread threadconference=</code><code>new</code> <code>thread(conference);</code>

<code>82</code>

<code>threadconference.start();</code>

<code>83</code>

<code>84</code>

<code>//22. 建立 10個 participant 對象,為每個對象各建立一個 thread 對象來運作他們,開始運作全部的線程。</code>

<code>85</code>

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

<code>86</code>

<code>    </code><code>participant p=</code><code>new</code> <code>participant(conference, &amp;quot;participant &amp;quot;+i);</code>

<code>87</code>

<code>    </code><code>thread t=</code><code>new</code> <code>thread(p);</code>

<code>88</code>

<code>    </code><code>t.start();</code>

<code>89</code>

它是怎麼工作的…

countdownlatch類有3個基本元素:

初始值決定countdownlatch類需要等待的事件的數量。

await() 方法, 被等待全部事件終結的線程調用。

countdown() 方法,事件在結束執行後調用。

當建立 countdownlatch 對象時,對象使用構造函數的參數來初始化内部計數器。每次調用 countdown() 方法, countdownlatch 對象内部計數器減一。當内部計數器達到0時, countdownlatch 對象喚醒全部使用 await() 方法睡眠的線程們。

不可能重新初始化或者修改countdownlatch對象的内部計數器的值。一旦計數器的值初始後,唯一可以修改它的方法就是之前用的 countdown() 方法。當計數器到達0時, 全部調用 await() 方法會立刻傳回,接下來任何countdown() 方法的調用都将不會造成任何影響。

此方法與其他同步方法有這些不同:

countdownlatch 機制不是用來保護共享資源或者臨界區。它是用來同步一個或者多個執行多個任務的線程。它隻能使用一次。像之前解說的,一旦countdownlatch的計數器到達0,任何對它的方法的調用都是無效的。如果你想再次同步,你必須建立新的對象。

以下截圖是例子的執行輸出:

線程同步工具(三)等待多個并發事件完成

你可以發現最後的參與者到達後,内部計數器一到達0,countdownlatch對象就叫醒全部的 videoconference 對象,他們全部輸出資訊表示video conference可以開始了。

更多…

countdownlatch 類有另一種版本的 await() 方法,它是:

await(long time, timeunit unit): 此方法會休眠直到被中斷; countdownlatch 内部計數器到達0或者特定的時間過去了。timeunit 類包含了:days, hours, microseconds, milliseconds, minutes, nanoseconds, 和 seconds.

繼續閱讀