在作性能測試的過程當中,我寫了兩個虛擬類ThreadLimitTimeCount
和ThreadLimitTimesCount
作框架,經過對線程的標記來完成超時請求的記錄。舊方法以下:java
@Override protected void after() { requestMark.addAll(marks); marks = new ArrayList<>(); GCThread.stop(); synchronized (this.getClass()) { if (countDownLatch.getCount() == 0 && requestMark.size() != 0) { Save.saveStringList(requestMark, MARK_Path.replace(LONG_Path, EMPTY) + Time.getDate().replace(SPACE_1, CONNECTOR)); requestMark = new Vector<>(); } } }
其中我用了synchronized
關鍵字同步,可是在匿名類的單元測試中出現一個BUG,匿名類中沒有實現clone()
方法,也不能直接使用深拷貝方法,致使沒法直接複製對象,因此我建立了多個功能相同的匿名線程類。問題來了,在代碼執行過程當中,偶然會出現記錄markrequest
的文檔中出現空內容的形式。編程
我查詢了一些資料,感受問題出如今synchronized (this.getClass())
這個問題了,由於我打印this.getClass()
給個人是當前測試類的類名,感受緣由就是匿名類的問題,匿名類至關於多個實現類,synchronized (this.getClass())
沒法保證多各種對象同時訪問這個方法的線程安全。最終,我選擇了另一種方式,就是單獨寫一個線程安全的save()
方法,這樣就能夠保證全部訪問保存方法的線程的安全,將清空記錄列表的功能也放在了這個線程安全的方法裏了。安全
/** * 同步save數據,用於匿名類多線程保存測試數據 * * @param data * @param name */ public static void saveStringListSync(Collection<String> data, String name) { synchronized (Save.class) { if (data.isEmpty()) return; saveStringList(data, name); } }
原來虛擬類的方法就變成了以下的樣子:多線程
if (countDownLatch.getCount() == 0 && requestMark.size() != 0) { Save.saveStringListSync(requestMark, MARK_Path.replace(LONG_Path, EMPTY) + Time.getDate().replace(SPACE_1, CONNECTOR)); }