場景:並發多線程,往Set集合中存放數據時,發現最終的數量結果不對,經過排查,沒有使用線程安全的Set導致
哈哈,不會描述,代碼解釋一切,下面代碼,使用的 Sets.newHashSet() 和 Collections.synchronizedSet(Sets.newHashSet()) 兩種方式,來聲明一個Set集合,其中第一個不是線程安全,第二個是線程安全
代碼:
public static void main(String[] args) { ExecutorService executor = new ThreadPoolExecutor( 10, 20, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(100000), threadFactory); //放入0-69999數字的字符串,沒有重復的 List<String> numList = Lists.newArrayList(); for (int i = 0; i < 70000; i++) { numList.add(String.valueOf(i)); } //將集合按2000一組分隔 List<List<String>> tmpNumList = ToolsUtil.spliceArrays(numList, 2000); //多線程運行 List<Future<Integer>> futureList = new ArrayList<>(); Set<String> numSet = Sets.newHashSet(); Set<String> numSyncSet = Collections.synchronizedSet(Sets.newHashSet()); tmpNumList.forEach(list -> futureList.add(executor.submit(() -> { list.forEach(num -> { numSet.add(num); numSyncSet.add(num); }); return 1; }))); futureList.forEach(future -> { try { future.get(); } catch (Exception e) { logger.warn("error,", e); } }); //結果輸出 System.out.println("線程不安全的Set:" + numSet.size()); System.out.println("線程安全的Set:" + numSyncSet.size()); }
控制台輸出:(運行多次,線程不安全的數字一直變動,且不正確)