应届生小白工作日记-多线程

 一、背景

最近在工作中需要调用其他服务的接口,这个接口限制只能单次调用,而我这边服务的需要调用几百次,emm...首先想到的肯定是循环调用,然后把每次返回的结果存到数组中,最后就得到了完整的数据。但是问题也随之而来,循环调用700次整个过程大概耗时5分钟左右。这个时长显然是无法让人接受的。于是想到了多线程调用来提高效率。

二、解决方案

首先创建一个线程池,然后循环遍历需要调用的业务,使用submit方法把任务丢进池子中。

private static final ThreadPoolExecutor executor = 
            new  ThreadPoolExecutor(20, 25, 60L,
            TimeUnit.SECONDS, 
            new LinkedBlockingQueue<>(), 
            new ThreadPoolExecutor.CallerRunsPolicy());
//用于存放请求接口的数据
ArrayList<Object> appUrlInfos = new ArrayList<>();
//计数器等待线程任务执行完,主线程才执行
CountDownLatch count = new CountDownLatch(userdata.size());
for (Object userdataUrl : userdata) {
     executor.submit(() -> {
     //构造请求体
     try {
            //请求接口 部分代码省略
            String response = OkHttpUtils.builder().url(requestUrl)
                        .post(req_body.toJSONString()).sync();
                                                
            appUrlInfos.add(JSONObject.parseObject(response));
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            count.countDown();
        }
    });
}
        count.await();

写完之后跑了一下发现新的问题又出现了,调了800次接口,数组应该800个元素才对,但是结果只有794个,这六个难道是多线程执行的过程中任务丢了?但是也没有道理呀,因为使用的是LinkedBlockingQueue,队列长度是默认的是Integer.Max,并不会触发线程池的拒绝策略。

百思不得其解,无奈之下只好打断点去逐步排查,最终发现多线程并没有丢任务,每个任务都被执行了,那数组的长度不够,会不会是添加这一行代码出了问题呢?想到这里看了看数组果然,ArrayList是一个现场不安全的数组,在高并发的情况下,可能会出现多个线程同时对数组添加了元素,但只有一个生效了,所以导致这样的问题发生。找到问题所在那就很好解决了,换一个线程安全的数组就可以啦用Vector代替或者使用Collections包装类中的synchronizedList方法。最终使用了Collections.synchronizedList(appUrlInfos)就解决了这个问题。

重要的事情说三遍!!!

只要使用到了多线程就一定要考虑线程安全问题

只要使用到了多线程就一定要考虑线程安全问题

只要使用到了多线程就一定要考虑线程安全问题

​​​​​​​

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值