美文网首页
线上踩坑-Java集合线程安全问题

线上踩坑-Java集合线程安全问题

作者: 花醉霜寒 | 来源:发表于2020-05-06 20:31 被阅读0次

\color{green}{踩坑回顾}
此前有个汇聚功能的响应时间特别长,走查代码发现以前版本完全用单线程来实现的,我将这个功能简单的抽象了一下,代码实现如下所示:

public class ListThreadSafeTest {
    public static void main(String[] args) throws InterruptedException {
        List<String> list =  new ArrayList<>();
        for(int j = 0; j < 800; j++) {
            //do something
            list.add("aa");
        }
        System.out.println(list.size());
    }
}

采用单线程的方式,业务逻辑为cpu密集型的,当数据量比较大的时候,采用单线程for循环的方式处理,性能可想而知。后来我用CountDownLatch对代码进行了改造,如下所示

public class ListThreadSafeTest {

    public static void main(String[] args) throws InterruptedException {
        List<String> list =  new ArrayList<>();
        //测试代码,这里就不追求细节了
        Executor executor = Executors.newFixedThreadPool(8);
        CountDownLatch latch = new CountDownLatch(8);
        for(int i = 0; i < 8 ; i++) {
            executor.execute(() -> {
                List<String> list1 = new ArrayList<>();
                for(int j = 0; j < 100; j++) {
                    list.add("aa");
                }
                latch.countDown();
            });
        }
        latch.await();
        System.out.println(list.size());
    }
}

测试性能提升十分明显,但是上线之后,该功能出现了大量数据不准确的情况,即list.size()的值不是800,而是随机出现一个小于800的结果,后来排查问题的时候想到,ArrayList不是线程安全的集合,在多线程并发写的过程中会出现线程安全问题,为了解决线程安全问题引入了一个线程安全的集合类ConcurrentHashMap来保存中间结果,问题解决。后来我用HashMap代替ConcurrentHashMap试了一下,同样会出现问题,因为HashMap也是非线程安全的。

public class ListThreadSafeTest {

    public static void main(String[] args) throws InterruptedException {
        List<String> list =  new ArrayList<>();
        //Map<String, List<String>> map = new HashMap<>();
        Map<String, List<String>> map = new ConcurrentHashMap<>();
        //测试代码,这里就不追求细节了
        Executor executor = Executors.newFixedThreadPool(8);
        CountDownLatch latch = new CountDownLatch(8);
        for(int i = 0; i < 8 ; i++) {
            executor.execute(() -> {
                List<String> list1 = new ArrayList<>();
                for(int j = 0; j < 100; j++) {
                    list1.add("aa");
                }
                map.put(UUID.randomUUID().toString(), list1);
                latch.countDown();
            });
        }
        latch.await();
        map.forEach((key, value) -> {
            list.addAll(value);
        });
        System.out.println(list.size());
    }
}

\color{green}{踩坑感想}
平常把高并发和线程安全挂在嘴边,真正到运用的时候却出现这种比较低级的错误,看来学知识还是不能仅限于表面,学以致用才是王道。

相关文章

  • 线上踩坑-Java集合线程安全问题

    此前有个汇聚功能的响应时间特别长,走查代码发现以前版本完全用单线程来实现的,我将这个功能简单的抽象了一下,代码实现...

  • parallelStream遇到的坑

    Java parallelStream遇到的坑 线程安全问题 paralleStream是并行流,并行就意味着是多...

  • 集合类与Java锁浅析

    集合类不安全问题 List ArrayList不是线程安全类,在多线程同时写的情况下,会抛出java.util.C...

  • volatile关键字

    线程安全问题 Java多线程带来的一个问题是数据安全问题,判断一段Java代码是否有线程安全问题可从以下几点入手:...

  • 线程安全问题

    线程安全问题 本篇主要讲解 线程安全问题,演示什么情况下会出现线程安全问题,以及介绍了 Java内存模型 、vol...

  • java多线程(壹)——线程与锁

    线程与线程安全问题 所有的线程安全问题都可以概况为三个点:原子性,可见性、有序性——————by Java多线程编...

  • java 线程安全问题的解决办法 和死锁

    线程安全问题的解决办法 线程 安全问题的解决方案:sun提供了线程同步机制让我们解决这类问题的。 java线程同步...

  • 关于Java中的 CopyOnWriteArraySet

    最近做的课程设计中用到了Java线程安全的集合类,因此关于对Java线程安全集合类的理解做个简单记录。Java集合...

  • Java集合中的线程安全问题

    介绍 JDK中提供了很多集合实现,本文不会介绍有哪些集合的接口以及实现类,而是介绍如何在多线程情况下使用这些集合。...

  • 「Java面试必会」谈谈并发包java .util.concur

    说到集合,就知道有的集合类并不是线程安全的,那Java中怎么保证集合是线程安全的? java .util.conc...

网友评论

      本文标题:线上踩坑-Java集合线程安全问题

      本文链接:https://www.haomeiwen.com/subject/thywghtx.html