java並發編程實戰:第十二章---並發程式的測試

來源:互聯網
上載者:User

標籤:alt   集合   經驗   strong   bugs   訊號量   否則   override   阻塞   

並發程式中潛在錯誤的發生並不具有確定性,而是隨機的。

安全性測試:通常會採用測試不變性條件的形式,即判斷某個類的行為是否與其規範保持一致

活躍性測試:進展測試和無進展測試兩方面,這些都是很難量化的(效能:即輸送量,響應性,延展性測試)

 

一、正確性測試

重點:找出需要檢查的不變性條件和後驗條件

1、對基本單元的測試——串列的執行

 1 public class BoundedBufferTests { 2      3     @Test 4     public void testIsEmptyWhenConstructed(){ 5         BoundedBuffer<String> bf = new BoundedBuffer<String>(10); 6         assertTrue(bf.isEmpty()); 7     } 8      9     @Test10     public void testIsFullAfterPuts() throws InterruptedException{11         BoundedBuffer<String> bf = new BoundedBuffer<String>(10);12         for (int i=0; i<10; i++){13             bf.put("" + i);14         }15         assertTrue(bf.isFull());16         assertTrue(bf.isEmpty());17     }18 }

2、對阻塞操作的測試

  每個測試必須等他建立的所有線程結束後才可以結束(join)

  要測試一個方法的阻塞行為,類似於測試一個拋出異常的方法:如果這個方法可以正常返回,那麼就意味著測試失敗。

  在測試方法的阻塞行為時,將引入額外的複雜性:當方法被成功地阻塞後,還必須使方法解除阻塞。(中斷)

 

 1 public void testTaskBlocksWhenEmpty(){ 2     final BoundedBuffer<Integer> bb = new BoundedBuffer<>(10); 3     Thread taker = new Thread(){ 4         @Override 5         public void run() { 6             try { 7                    int unused =  bb.take(); 8                 fail(); //不應執行到這裡 9             } catch (InterruptedException e) {10             }11         }12     };13     try {14         taker.start();15         Thread.sleep(1000);16         taker.interrupt();17         taker.join(2000); //保證即使taker永久阻塞也能返回18         assertFalse(taker.isAlive());19     } catch (InterruptedException e) {20         fail();21     }22 }

 

3、安全性測試

  構建對並發類的安全性測試中,需要解決的關鍵問題在於,要找出那些容易檢查的屬性,這些屬性在發生錯誤的情況下極有可能失敗,同時又不會使得錯誤檢查代碼人為地限制並發性。理想的情況是,在測試屬性中不需要任何同步機制

例:通過計算入列和出列的校正和進行檢驗(使用柵欄保證線程均運行到可檢驗處再檢驗)

4、資源管理測試

對於任何持有或管理其他對象的對象,都應該在不需要這些對象時銷毀對它們的引用

例:使用堆檢驗工具對記憶體資源使用進行檢驗

5、使用回調

可以通過自訂擴充類來進行相關測試

 

 1 public class TestingThreadFactory implements ThreadFactory { 2     public final AtomicInteger numCreated =  3             new AtomicInteger(); //記錄建立的線程數 4     private final ThreadFactory factory =  5             Executors.defaultThreadFactory(); 6      7     @Override 8     public Thread newThread(Runnable r) { 9         numCreated.incrementAndGet();10         return factory.newThread(r);11     }12 }

6、產生更多的交替操作

使用yield、sleep命令更容易使錯誤出現

 

二、效能測試

效能測試的目標:

  • 衡量典型測試案例中的端到端效能,獲得合理的使用情境
  • 根據經驗值來調整各種不同的限值,如線程數量,緩衝容量等

1、計時器

通過增加計時器,並改變各個參數、線程池大小、緩衝大小,計算出已耗用時間

例:

2、多種演算法的比較

使用不同的內部實現演算法,找出具有更高的延展性的演算法

例:

3、響應性衡量

某個動作經過多長時間才能執行完成,這時就要測量服務時間的變化情況

除非線程由於密集的同步需求而被持續的阻塞,否則非公平的訊號量通常能實現更好的輸送量,而公平的訊號量則實現更低的變動性(公平性開銷主要由於線程阻塞所引起)

 

三、避免效能測試的陷阱

1、記憶體回收

 

  • 保證記憶體回收在執行測試程式期間不被執行,可通過-verbose:gc查看記憶體回收資訊。
  • 保證記憶體回收在執行測試程式期間執行多次,可以充分反映出運行期間的記憶體配置和記憶體回收等開銷。

2、動態編譯

 

  • 可以讓測試程式運行足夠長時間,防止動態編譯對測試結果產生的偏差。
  • 在HotSpot中設定-xx:+PrintCompilation,在動態編譯時間輸出一條資訊

3、對代碼路徑不真實採樣

  • 動態編譯可能會讓不同地方調用的同一方法產生的程式碼不同
  • 測試程式不僅要大致判斷某個典型應用程式的使用模式,還要盡量覆蓋在該應用程式中將執行的代碼路徑集合

4、不真實的競爭程度

  • 不同的共用資料和執行本地計算的比例,將表現出不同的競爭程度,也就有不同的效能和延展性

5、無用代碼的消除

  • 編譯器可能會刪除那些沒有意義或不會產生結果或可預測結果的代碼
  • 使結果盡量是不可預測的 

四、其他測試方法

代碼審查(人工檢查代碼),競態分析工具(FindBugs,CheckStyle),面向方面的測試技術,分析與偵查工具(jvisualvm)

java並發編程實戰:第十二章---並發程式的測試

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.