如何調試多線程的程序?
03-15
> Junit本身是不支持普通的多線程測試的,這是因為Junit的底層實現上,是用System.exit退出用例執行的,主線程終止jvm都停了,其他線程肯定執行不了了(具體分析查看源碼org.junit.runner.JUnitCore)。# 文檔官網:http://groboutils.sourceforge.net# 示例```
net.sourceforge.groboutils groboutils-core 5 ``````public class ThreadJunitDemo { private static final int THREAD_COUNT = 10; @Test
推薦閱讀:
@Repeat(1)
public void testThreadJunit() throws Throwable { try { //Runner數組,相當於並發多少個 TestRunnable[] trs = new TestRunnable[THREAD_COUNT]; for (int i = 0; i < THREAD_COUNT; i++) { trs[i] = new TestRunnable() { @Override public void runTest() throws Throwable { commMethod();}
}; } // 用於執行多線程測試用例的Runner,將前面定義的單個Runner組成的數組傳入 MultiThreadedTestRunner mttr = new MultiThreadedTestRunner(trs); // 開發並發執行數組裡定義的內容 mttr.runTestRunnables(); } catch (Throwable e) { e.printStackTrace(); }}
private void commMethod() throws Exception { System.out.println("===" + Thread.currentThread().getId() + "begin to execute ..."); for (int i = 0; i <10; i++) { int a = i*5; System.out.println(a); } System.out.println("===" + Thread.currentThread().getId() + "end to execute ..."); }}
```## TestRunnable表示一個測試線程,實例需要實現該類的runTest()方法,在該方法中寫自己用的測試代碼。## MultiThreadedTestRunner表示需要測試的線程,相當與一個ExecuteService,可以用來執行TestRunnable,構造函數需要傳入TestRunnable數組。調用MultiThreadedTestRunner.runTestRunnables() 方法啟動測試線程,開始執行測試。## TestMonitorRunnable表示監控線程,可以讓每一個TestRunnable對應一個TestMonitorRunnable,在TestMonitorRunnable中監控TestRunnable,TestMonitorRunnable是TestRunnable的子類。# 總結GroboUtils使得擴展Java測試變得可能,常常被用於多線程測試,整體單元測試,代碼覆蓋工具。接下來,根據文章的demo去測試一下吧。
程序的線程模型應該能在一張 A4 紙上畫出來,有哪些線程,幹什麼活,各路消息來了經過哪些處理步驟,涉及哪些線程,會訪問哪些共享數據,等等。
這樣就算最初的作者離開團隊,後面的維護者也不會輕易破壞這個設計。要知道,一個看似無害的局部代碼修改,有可能造成 data race,如果混過了code review,那麼就埋雷了,輕則程序崩潰,重則破壞數據。理解程序的線程設計,才能最大限度地防止這一情況的出現。最後,動態和靜態的分析工具也可以派上用場,例如 Valgrind、ThreadSanitizer。推薦閱讀: