我们都知道多线程是为了加快数据处理的,但至于怎么用,因为在工作中,我一直很少用,所以对多线程不是很了解。之前处理一个功能时,由于没有经验,导致速度很慢,前一段时间经老大提示,可以用多线程解决,突然发现原来多线程可以这么用可以来处理这一类问题,今天记录一下,作为笔记也作为一个给读者的参考,好了先说一下问题:公司的业务的业务不仅分模块而且是分库分表的,这样就导致一个问题,当我们要查询一个数据时,不能连表查询,不能只通过一个接口获得数据,最容易想到的常规做法就是:


public List<Data> queryDatas() {  
List<Data> datas = queryDataFromDB();  
if(null != datas && datas.size() > 0) {  
for(Data data : datas) {  
Object object = getObjectFromDb(data.getId());  
data.setAttr1(object.getAttr);  
}  
}

return datas;  
}

这么做,虽然可以满足业务需求,但效率实在是太低了,尤其是列表数据越大时,如果不只一个属性要这么做时,速度是会慢到要死人的。所以经老大提示参考同事的实现就采用了如下方法:


private static final ExecutorService executor = Executors.newFixedThreadPool(20);

public List<Data> queryDatas() {  
List<Data> datas = queryDataFromDB();  
if(null != datas && datas.size() > 0) {  
batchSetAttr(datas);  
}  
return datas;  
}

private boolean batchSetAttr(final List<Data> datas) {  
final CompletionService<Data> completionService = new ExecutorCompletionService<>(executor);  
for (final Data data : datas) {  
completionService.submit(new Callable<Data>() {  
@Override  
public Data call() throws Exception {  
Object object = getObjectFromDb(data.getId());  
data.setAttr1(object.getAttr);  
return data;  
}  
});  
}

try {  
for (int i = 0, size = datas.size(); i < size; i++) {  
Future<Data> future = completionService.take();  
Data d = future.get();  
}  
} catch (InterruptedException e) {  
logger.error("InterruptedException", e);  
return false;  
} catch (ExecutionException e) {  
logger.error("ExecutionException", e);  
return false;  
}

return true;  
}

利用多线程批量查询,返回时一一设置值,最终达到提高速度的目的。
最后需要说明一点:线程池的大小,大家可以根据自己的实际情况来设置,并不是越大越好;