java8 关于Set集合的线程安全使用

场景:并发多线程,往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());
    }

控制台输出:(运行多次,线程不安全的数字一直变动,且不正确)

 

posted @ 2019-12-02 17:01  一问三不知。  阅读(5564)  评论(0编辑  收藏  举报