在當今世界,軟體開發的應用必須工作正常,要達到公司的品質标準,還要在将來可以很容易的修改,而且不僅要在有限的時間内,還要盡可能低的費用支出。為了到達這個目标,必需使用 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()) &&(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,是以進入休眠,而其他的線程還在運作:
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIn5GcuETL40COvwFOw8CXzEDMy8CXzRWYvxGc19CX05WZ052bj1Cc39CXt92YuUmdlZWavw1LcpDc0RHaiojIsJye.png)
20. 暫停主線程的運作。選擇線程,右鍵單擊,然後線程suspend選項。以下的裁圖展示的是新的debugging視窗外觀。請看下面的裁圖:
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檢測器檢查到的,如你在以下裁圖中看到的:
更多…
有一些控制debugger的選項。在tools 菜單選擇 options 選項。然後,選擇 miscellaneous 選項,和 java debugger 标簽。以下截圖是視窗的外觀:
在視窗中有2個選項可以控制之前描述的行為:
新 breakpoints 暫停:這個選項,你配置netbeans的線上程中尋找breakpoint的行為。你可以隻暫停有breakpoint的線程或者應用的全部線程。
步驟恢複:這個選項,你配置netbeans恢複一個線程時的行為。你可以隻恢複目前線程或者全部線程。2個選項都在之前的展示的裁圖中标明了。
參見
第八章,測試并發應用:配置eclipse來調試并發代碼