java多线程的一个应用场景
调用接口的实际场景
在很多项目中都会有调用其他系统接口的情况,有的接口效率正常,有的接口慢的要死,慢到头绿。本人在实际中遇到过一个响应时间10s以上的接口,并且因为业务要求需要调用该接口很多次(10000+),说白了就是单次的传参数获取一些数据,单个接口的数据量很小,但是对方没有提供批量数据获取的接口,木的办法。
那么就单纯的以10s来计算,调用10000次也就是10w秒,大该要28个小时(这谁受得了),于是作为刚毕业不到两年的我终于想到了用多线程来暂时解决这个问题,用很简单的思维来想,起码我用10个线程来跑,是不是就只需要2.8个小时了?(还是接受不了)好在短时间内一批数据只用调用一次接口,多搞点线程几十分钟也能还能满足需求。
多线程解决思路
于是开始整线程,思路很清晰→,
1、均分参数集合,将传递的参数List分成10个(就先按10个线程来跑吧)。这里有个小问题,如何将list平均分配为10个list,整数的当然很好弄,我最开始的想法是:如果list不是能整除10的,就除以9,前面9个是平均的,剩下的余数归给最后一个。(最后一个肯定少)这种方法不值得写出来。于是在网上看到一个较为优质的方法
源自于https://blog.csdn.net/u010523770/article/details/54585261/
public static <T> List<List<T>> averageAssign(List<T> source,int n) {
List<List<T>> result = new ArrayList<List<T>>();
int remaider = source.size() % n; //(先计算出余数)
int number = source.size() / n; //然后是商
int offset = 0;//偏移量
for (int i = 0; i < n; i++) {
List<T> value = null;
if (remaider > 0) {
value = source.subList(i * number + offset, (i + 1) * number + offset + 1);
remaider--;
offset++;
} else {
value = source.subList(i * number + offset, (i + 1) * number + offset);
}
result.add(value);
}
return result;
}
2、写线程,线程里面自然是用分好的list数据去循环调用接口获取数据,获取后的数据需要入库,于是循环完后进行一个批量插入。这里开始有一个小问题:我该如何用线程拿到我分好的list。 我的解决方案是在线程类里面写一个该list的泛型属性,通过set或者构造函数来将数据传给每个线程。
public class GetHouseDataThread extends Thread{
private List<T> lists= new ArrayList<T>();
public List<T> getLists() {
return lists;
}
public void setLists(List<T> lists) {
this.lists= lists;
}
public void run(){
//调用接口,就懒得写了
}
}
3、启动线程 ,写好代码启动完事儿。但是这里我需要的线程跑完后,主线程的代码才能继续执行,比如全部跑完,最后提示“多线程获取数据成功多少多少数据”之类的,这样的话我就需要在其他线程进行的时候,主线程等待,其他线程跑完了主线程继续。这里我试过join,但是对所有线程join就没用了,主线程是等待了,其他线程也等待了。(可能我还没找到join的精髓)之后我采取的是 CountDownLatch这个类,(不知道的朋友可以自行百度一下),我的理解这玩意儿可以作为一个监听计数器,自行设置线程结束后计数器减一,主线程中使用countDownLatch.await();等待计数器归零,归零前主线程就挂着。如下:
首先在xxxx类里面搞一个属性,最好是静态final的,我的线程是10个,所以构造函数里面为10;
public static final CountDownLatch countDownLatch = new CountDownLatch(10);
然后在调用接口的线程中使用下面的方法。即可将计数器减一。
xxxx.countDownLatch.countDown();
然后在开启线程的代码后面添加上xxxx.countDownLatch.await(); (完美的解决了我主线程等待子线程运行完在继续运行的问题,开心的一批)
以上就是java项目中实际需要运用多线程的一个场景,如有问题可以大方的发出来一起探讨