利用FutureTask和ExecutorService实现一个任务拆分成多个任务,实现性能提高
2016-01-06 00:00
387 查看
摘要: 利用FutureTask和ExecutorService实现一个任务拆分成多个任务,多线程实现性能提
业务场景:本地服务开发的时候,本地有个H服务,H想要查询一个展示数据的列表,就远程调用了A服务,A服务需要远程调用B服务,拿到一个list,拿到List之后,需要循环这个list,然后对List中的每个值进行循环,调用C服务和D服务 获得真正需要的数据。
遇到的问题:由于A服务拿到的List可能会比较大!!!估计在1000左右,然后如果单线程执行,需要循环这个list,然后针对list里的每一项,再去调用C和D服务,虽然单个调用比较快,但是因为是跨服务调用,循环1000次,会导致H服务这边远程调用超时,这种情况下造成查询不稳定。经常出现timeout
目前的解决方案:把这个大List进行拆分,然后多线程并发操作,以提升性能,降低远程调用的耗时。
期待反馈:希望大家看完后,能提出更有效的解决方案。
示例代码如下:
业务场景:本地服务开发的时候,本地有个H服务,H想要查询一个展示数据的列表,就远程调用了A服务,A服务需要远程调用B服务,拿到一个list,拿到List之后,需要循环这个list,然后对List中的每个值进行循环,调用C服务和D服务 获得真正需要的数据。
遇到的问题:由于A服务拿到的List可能会比较大!!!估计在1000左右,然后如果单线程执行,需要循环这个list,然后针对list里的每一项,再去调用C和D服务,虽然单个调用比较快,但是因为是跨服务调用,循环1000次,会导致H服务这边远程调用超时,这种情况下造成查询不稳定。经常出现timeout
目前的解决方案:把这个大List进行拆分,然后多线程并发操作,以提升性能,降低远程调用的耗时。
期待反馈:希望大家看完后,能提出更有效的解决方案。
示例代码如下:
package test11; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.FutureTask; /** * @author : mingwu.lxm * @version 创建时间:2016年1月5日 下午8:23:09 * 类说明 解决计算一个类的两个数相加,放到sum类中 */ public class TestFutureTask { public static void main(String[] args) throws InterruptedException, ExecutionException { int size =6; List<UserInfo> userInfoList = new ArrayList<UserInfo>(); //存储本地串行计算花费的时间 List<UserInfo> retInfoList1 = new ArrayList<UserInfo>(); //存储多线程计算花费的时间 List<UserInfo> retInfoList2 = new ArrayList<UserInfo>(); for (int i = 0; i < 1000; i++) { UserInfo uc = new UserInfo(); uc.setMoneyA((int) (Math.random()*100)); uc.setMoneyB((int) (Math.random()*100)); userInfoList.add(uc); } //准备要执行的数据,数据整备完毕 ExecutorService es = Executors.newFixedThreadPool(100); Long aDateLong = System.currentTimeMillis(); for (int i = 0; i < userInfoList.size(); i++) { int sum = userInfoList.get(i).getMoneyA()+userInfoList.get(i).getMoneyB(); userInfoList.get(i).setSumNum(sum); retInfoList1.add(userInfoList.get(i)); //线程睡眠以模仿计算消耗的时间 Thread.sleep(1); } Long bDateLong = System.currentTimeMillis(); System.out.println("串行进行的耗时:"+ (bDateLong-aDateLong)); List<List<UserInfo>> subTaskList = new ArrayList<List<UserInfo>>(); //切分任务 for (int i =0 ;i<=userInfoList.size();i=i+size) { subTaskList.add(userInfoList.subList(i, Math.min(i+size, userInfoList.size()))); } Long aDateLong2 = System.currentTimeMillis(); //这个list是专门用来保存所有的future的,先把所有任务全部扔出去执行,这时候不管结果 List<FutureTask<List<UserInfo>>> tasklist = new ArrayList<FutureTask<List<UserInfo>>>(); for (List<UserInfo> alist : subTaskList) { FutureTask<List<UserInfo>> task = new FutureTask<List<UserInfo>>(new SumJob(alist)); es.execute(task); tasklist.add(task); } //拿到所有的结果 for (FutureTask<List<UserInfo>> futureTask : tasklist) { retInfoList2.addAll(futureTask.get()); } Long bDateLong2 = System.currentTimeMillis(); System.out.println("多线程拆分后耗时:"+ (bDateLong2-aDateLong2)); System.out.println(retInfoList1.size()); System.out.println(retInfoList2.size()); } } //求和的线程任务 class SumJob implements Callable<List<UserInfo>>{ private List<UserInfo> sumList=null; public SumJob(List<UserInfo> sumList) { super(); this.sumList = sumList; } @Override public List<UserInfo> call() throws Exception { for (int i = 0; i < sumList.size(); i++) { int sum = sumList.get(i).getMoneyA()+sumList.get(i).getMoneyB(); sumList.get(i).setSumNum(sum); //线程睡眠以模仿计算消耗的时间 Thread.sleep(1); } return sumList; } }
相关文章推荐
- GeoJSON
- 一.Properties类与Properties配置文件
- springMVC实现excel导出(简单封装版)
- MySql 学习笔记
- 索引【备档】
- java如何使用存储过程,持续更新
- iOS 通知
- (mkdocs)一款使用markdown编写website的插件
- Ubuntu快捷方式的描述
- 百度告警-Nagios接入,全方位告警接入,电话/短信/微信
- mysql设置允许任何主机访问
- git ignore not work
- Could not find acceptable representation异常
- 使用Word2010发布OsChina博客
- 为什么要使用maven 和 git
- Maven ---唯快不破
- 每日一模式之委托模式
- 每日一模式之原型模式
- 每日一模式之外观模式
- 活着总得有点追求,展望2016