场景:并发多线程,往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()); }
控制台输出:(运行多次,线程不安全的数字一直变动,且不正确)