通常來說,多線程的並發及條件斷點的debug是很難完成的,或許本篇文章會給你提供一個友好的調試方法。讓你在多線程開發過程中的調試更加的有的放矢。
我們將通過一個例子來學習。在這里,我編寫了一個多線程程序來計算此數學問題:100! + 100000!
。即:100的階乘 + 100000的階乘。
數學不好的同學看這里,100 階乘就是:1 * 2 * 3 * …… * 100 = ? ,簡寫為100!
import java.math.BigInteger;
public class MathProblemSolver {
//開啟兩個線程
public static void main(String arg[]){
//第一個線程計算 100!
FactorialCalculatingThread thread1 = new FactorialCalculatingThread(100);
//第二個線程計算 100000!
FactorialCalculatingThread thread2 = new FactorialCalculatingThread(100000);
thread1.setName("Thread 1");
thread2.setName("Thread 2");
thread1.start();
thread2.start();
try {
thread1.join(); //線程Jion,以使主線程在“線程1”和“線程2”都返回結果之前不會進一步執行
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
BigInteger result = thread1.getResult().add(thread2.getResult());
System.out.println("將兩個線程的計算結果相加等於:" + result);
}
//用於階乘計算的線程類
private static class FactorialCalculatingThread extends Thread {
private BigInteger result = BigInteger.ONE;
private long num;
public FactorialCalculatingThread(long num) {
this.num = num;
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " 開始階乘的計算:" + num);
factorialCalc(num);
System.out.println(Thread.currentThread().getName() + "執行完成");
}
//數的階乘計算方法
public void factorialCalc(long num) {
BigInteger f = new BigInteger("1");
for (int i = 2; i <= num; i++)
f = f.multiply(BigInteger.valueOf(i));
result = f;
}
public BigInteger getResult() { return result; }
}
}
上面的代碼解釋
- 開啟兩個線程,“Thread 1”計算(100!)和“Thread 2”計算(100000!)
- 在main()方法中啟動兩個線程,然后調用
thread1.join()
和thread2.join()
,以使主線程在“線程1”和“線程2”都返回結果之前不會進一步執行。 - 最后將兩個線程的計算結果相加,得到
100! + 100000!
下面就讓我們使用IntelliJ IDEA工具來調試這段多線程的代碼。
Frames 與 Thread 面板
調試工具窗口的“Frames”面板包含一個下拉菜單。它的關注點在:由於斷點而導致暫停的線程,並顯示這些線程的調用堆棧信息。在下圖中,斷點位於main()方法中如圖所示的位置,Frame向我們顯示了主線程的調用堆棧。
如果要檢查其他線程的調用堆棧,則可以從下拉列表中進行選擇。
Thread面板顯示當前處於活動狀態的所有線程。參考上面的代碼,我在thread1.join()
添加了一個斷點。當應用程序在該斷點處暫停時,我們應該在此窗格中至少看到三個線程-“main”,“Thread 1”和“Thread 2”(請看下面的屏幕截圖)。您可以雙擊每個線程以觀察其調用堆棧。
條件斷點-只掛起符合條件的線程
假設我正在解決該程序中的錯誤,並且我只需要在“Thread 2”開始運行時就暫停執行。這表明我需要在FactorialCalculatingThread的run()方法的第一行上添加一個斷點。因為我們開啟的兩個線程使用的是同一段代碼,所以我們會遇到一個問題-使用該段代碼的所有線程遇到斷點都將被掛起,包括應用程序的“Thread 1”和“Thread 2”。我不希望兩個線程都暫停。該怎么做?
我們可以使用條件斷點功能。添加斷點后,右鍵單擊它,選中“suspend”並選擇“Thread”。然后我們添加條件currentThread().getName().equals("Thread 2")
,如下面的屏幕快照所示。此條件確保調試器僅在當前線程的名稱為“Thread 2”時才暫停當前線程:
現在執行調試程序,當應用暫停時,僅“Thread 2”被暫停。您可以通過以下步驟確認“Thread 1”已執行並且沒有被掛起:
1.在控制台中,您可以通過日志來驗證“Thread 1”已運行並退出。
2.在“Thread”面板中,可以看到此時已經沒有“Thread 1”,已經運行完成了!
在不同的IDE版本中,配置條件斷點的方式可能有所不同。但是關鍵思想是要意識到這些功能的存在並加以使用。
歡迎關注我的博客,里面有很多精品合集
- 本文轉載注明出處(必須帶連接,不能只轉文字):字母哥博客。
覺得對您有幫助的話,幫我點贊、分享!您的支持是我不竭的創作動力! 。另外,筆者最近一段時間輸出了如下的精品內容,期待您的關注。