利用FutureTask和ExecutorService实现一个任务拆分成多个任务,实现性能提高

原创
2016/01/06 14:03
阅读数 7.1K

业务场景:本地服务开发的时候,本地有个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;
	}
	
}


展开阅读全文
打赏
0
7 收藏
分享
加载中
更多评论
打赏
0 评论
7 收藏
0
分享
返回顶部
顶部