天天看點

測試并發應用(八)配置NetBeans來調試并發代碼

在當今世界,軟體開發的應用必須工作正常,要達到公司的品質标準,還要在将來可以很容易的修改,而且不僅要在有限的時間内,還要盡可能低的費用支出。為了到達這個目标,必需使用 ide,它集合了一個公共接口和多個工具(編譯器和調試器)為了友善應用程式的開發。

如果你使用 java 程式設計語言,那麼 netbeans 是最普遍的 ide之一。它有一個内置調試器(integrated debugger)允許你調試你的應用。在這個指南,你将學習如何改變配置來幫助測試并發應用。

準備

你應該安裝好 netbeans ide 。打開并建立一個新的java項目。

怎麼做呢…

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

<code>01</code>

<code>//1.   建立一個類,名為 task1,并一定實作 runnable 接口。</code>

<code>02</code>

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

<code>03</code>

<code>04</code>

<code>//2.   聲明2個私有 lock 屬性,名為 lock1 和 lock2。</code>

<code>05</code>

<code>private</code> <code>lock lock1, lock2;</code>

<code>06</code>

<code>07</code>

<code>//3.   實作類的構造函數,初始化它的屬性值。</code>

<code>08</code>

<code>public</code> <code>task1 (lock lock1, lock lock2) {</code>

<code>09</code>

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

<code>10</code>

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

<code>11</code>

<code>}</code>

<code>12</code>

<code>13</code>

<code>//4.   實作 run() 方法。首先,使用 lock() 方法來擷取 lock1 對象的控制,并寫資訊到操控台表明已經獲得了。</code>

<code>14</code>

<code>@override</code>

<code>15</code>

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

<code>16</code>

<code>lock1.lock();</code>

<code>17</code>

<code>system.out.printf(</code><code>"task 1: lock 1 locked\n"</code><code>);</code>

<code>18</code>

<code>19</code>

<code>//5. 然後,使用 lock() 方法來擷取 lock2 對象的控制,并寫資訊到操控台表明已經獲得了。</code>

<code>20</code>

<code>lock2.lock();</code>

<code>21</code>

<code>system.out.printf(</code><code>"task 1: lock 2 locked\n"</code><code>);</code>

<code>22</code>

<code>//最後,釋放這2個lock對象。先是 lock2 對象,然後 lock1 對象。</code>

<code>23</code>

<code>lock2.unlock();</code>

<code>24</code>

<code>lock1.unlock();</code>

<code>25</code>

<code>26</code>

<code>27</code>

<code>//6.  建立一個類,名為 task2,并一定實作 runnable 接口.</code>

<code>28</code>

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

<code>29</code>

<code>30</code>

<code>//7.    聲明2個私有 lock 屬性,名為 lock1 和 lock2。</code>

<code>31</code>

<code>32</code>

<code>33</code>

<code>//8.  實作類的構造函數,初始化它的屬性值。</code>

<code>34</code>

<code>public</code> <code>task2(lock lock1, lock lock2) {</code>

<code>35</code>

<code>36</code>

<code>37</code>

<code>38</code>

<code>39</code>

<code>//9.   實作 run() 方法。首先,使用 lock() 方法來擷取 lock2 對象的控制,并寫資訊到操控台表明已經獲得了。</code>

<code>40</code>

<code>41</code>

<code>42</code>

<code>43</code>

<code>system.out.printf(</code><code>"task 2: lock 2 locked\n"</code><code>);</code>

<code>44</code>

<code>45</code>

<code>//10. 然後,使用 lock() 方法來擷取 lock1 對象的控制,并寫資訊到操控台表明已經獲得了。</code>

<code>46</code>

<code>47</code>

<code>system.out.printf(</code><code>"task 2: lock 1 locked\n"</code><code>);</code>

<code>48</code>

<code>49</code>

<code>//11. 最後,釋放這2個lock對象。先是 lock1 對象,然後 lock2 對象。</code>

<code>50</code>

<code>51</code>

<code>52</code>

<code>53</code>

<code>54</code>

<code>//12. 建立例子的主類通過建立一個類,名為 main 并添加 main()方法。</code>

<code>55</code>

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

<code>56</code>

<code>57</code>

<code>//13. 聲明2個私有 lock 屬性,名為 lock1 和 lock2。</code>

<code>58</code>

<code>lock lock1, lock2;</code>

<code>59</code>

<code>lock1=</code><code>new</code> <code>reentrantlock();</code>

<code>60</code>

<code>lock2=</code><code>new</code> <code>reentrantlock();</code>

<code>61</code>

<code>62</code>

<code>//14. 建立 task1 對象,名為 task1。</code>

<code>63</code>

<code>task1 task1=</code><code>new</code> <code>task1(lock1, lock2);</code>

<code>64</code>

<code>65</code>

<code>//15. 建立 task2 對象,名為 task2。</code>

<code>66</code>

<code>task2 task2=</code><code>new</code> <code>task2(lock1, lock2);</code>

<code>67</code>

<code>68</code>

<code>//16. 使用2個線程執行這2個 tasks。</code>

<code>69</code>

<code>thread thread1=</code><code>new</code> <code>thread(task1);</code>

<code>70</code>

<code>thread thread2=</code><code>new</code> <code>thread(task2);</code>

<code>71</code>

<code>72</code>

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

<code>73</code>

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

<code>74</code>

<code>75</code>

<code>//17.  當2個任務還沒有結束他們的運作,每500毫秒就寫一條資訊給操控台。使用 isalive() 方法來檢查線程是否結束運作。</code>

<code>76</code>

<code>while</code> <code>((thread1.isalive()) &amp;&amp;(thread2.isalive())) {</code>

<code>77</code>

<code>    </code><code>system.out.println(</code><code>"main: the example is"</code><code>+ </code><code>"running"</code><code>);</code>

<code>78</code>

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

<code>79</code>

<code>        </code><code>timeunit.milliseconds.sleep(</code><code>500</code><code>);</code>

<code>80</code>

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

<code>81</code>

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

<code>82</code>

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

<code>83</code>

18. 添加一個breakpoint到 task1 類的run()方法 裡的第一個 println() 方法的調用。class.

19.調試此程式。你可以發現 debugging 視窗在 netbeans 的主視窗的左上角。以下的裁圖呈現的視窗外觀裡task1對象 由于到達了breakpoint,是以進入休眠,而其他的線程還在運作:

測試并發應用(八)配置NetBeans來調試并發代碼

20. 暫停主線程的運作。選擇線程,右鍵單擊,然後線程suspend選項。以下的裁圖展示的是新的debugging視窗外觀。請看下面的裁圖:

測試并發應用(八)配置NetBeans來調試并發代碼

21. 恢複被暫停的2個線程。選擇每個線程,右鍵單擊,選擇resume選項。

它是如何工作的…

當使用 netbeans 試調并發應用, 當試調器到達 breakpoint, 它暫停到達 breakpoint 的線程并在左上角的 debugging 視窗顯示目前正在運作的線程。

你可以使用視窗來暫停或者恢複目前在 pause 或者 resume選項中運作的線程。你也可以使用 variables 标簽來檢視線程的變量或者屬性的值。

netbeans 也包含了 deadlock 檢測器。當你在 debug 菜單選擇 check for deadlock 選項,netbeans 執行對應用的分析來試調決定是否有deadlock 情況。這個例子是很明顯的 deadlock。第一個線程首先獲得鎖lock1,然後鎖lock2。第二個線程獲得鎖與第一個相反的順序。breakpoint的插入導緻了deadlock,但是如果你使用 netbeans deadlock檢測器,你什麼也不會發現,是以應該慎重使用此選項。

使用 同步關鍵詞 改變在2個任務中的鎖,并再次調試程式。task1的代碼如以下的代碼:

<code>1</code>

<code>2</code>

<code>3</code>

<code>synchronized</code><code>(lock1) {</code>

<code>4</code>

<code>    </code><code>system.out.printf(</code><code>"task 1: lock 1 locked\n"</code><code>);</code>

<code>5</code>

<code>synchronized</code><code>(lock2) {</code>

<code>6</code>

<code>    </code><code>system.out.printf(</code><code>"task 1: lock 2 locked\n"</code><code>);</code>

<code>7</code>

<code>8</code>

<code>9</code>

task2類的代碼跟這個類似,隻是改變了locks的順序。如果你再此調試這個例子,你會再次得到deadlock,但是在這次方案,是被deadlock檢測器檢查到的,如你在以下裁圖中看到的:

測試并發應用(八)配置NetBeans來調試并發代碼

更多…

有一些控制debugger的選項。在tools 菜單選擇 options 選項。然後,選擇 miscellaneous 選項,和 java debugger 标簽。以下截圖是視窗的外觀:

測試并發應用(八)配置NetBeans來調試并發代碼

在視窗中有2個選項可以控制之前描述的行為:

新 breakpoints 暫停:這個選項,你配置netbeans的線上程中尋找breakpoint的行為。你可以隻暫停有breakpoint的線程或者應用的全部線程。

步驟恢複:這個選項,你配置netbeans恢複一個線程時的行為。你可以隻恢複目前線程或者全部線程。2個選項都在之前的展示的裁圖中标明了。

參見

第八章,測試并發應用:配置eclipse來調試并發代碼