我们经常会有这种需求,比如APP首页,需要同时加载20多个接口,你怎么做?一个个按顺序调用接口吗?如果网络通畅还好,如果网络不好,你可能会让首页加载几分钟,用户体验肯定不好,那么我们就需要使用多线程来做。那假设其中有几个接口需要都执行完了,你才能继续执行后面的代码,怎么做?那这时候就需要 ExecutorService中的 <T> Future<T> submit(Callable<T> task);方法了。
1.工具类FutureUtils.java
/**
*
*/
package com.figo.html5.future;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* 多线程执行任务 .
*
* @author figo . 20190711 add .
*/
public class FutureUtils{
/**
* SUCCESS .
*/
public static final String SUCCESS="1";
/**
*
* @param tasks .
* @return .
*/
public static boolean useFuture(List<BaseTask> tasks) {
long start = System.currentTimeMillis();
// 固定线程池线程个数
ExecutorService executor = Executors.newFixedThreadPool(tasks.size());
for(BaseTask task:tasks)
{
executor.submit(task);
}
executor.shutdown();
while (true) {
if (executor.isTerminated()) {
long end = System.currentTimeMillis();
System.out.println("所有任务执行完毕,总耗时(毫秒):" + (end - start));
return true;
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
2.BaseTask.java任务基类
package com.figo.html5.future;
import java.util.List;
import java.util.concurrent.Callable;
/**
* BaseTask.java .
*
* @author figo.zhu .
* @serial .
* @param <T> .
* @since 2019年7月11日 下午3:37:57 .
*/
public abstract class BaseTask<T> implements Callable<T> {
/**
* result list .
*/
List<T> listResult;
/**
* result .
*/
T result;
/**
*
* @return .
*/
public List<T> getListResult() {
return listResult;
}
/**
*
* @param listResult .
*/
public void setListResult(List<T> listResult) {
this.listResult = listResult;
}
/**
*
* @return .
*/
public T getResult() {
return result;
}
/**
*
* @param result .
*/
public void setResult(T result) {
this.result = result;
}
}
3.其中一个任务,查询商户开通的支付银行列表 QueryMerBankConfigTask.java,其他相似
/**
* QueryMerBankConfigTask.java
*
* @author sun.jun
* @serial
* @since 2019年7月11日 下午3:47:31
*/
package com.figo.html5.future;
import java.util.List;
import com.figo.service.impl.APBusServiceImpl;
import com.figo.util.log.MonitorLogger;
/**
* QueryMerBankConfigTask.java .
*
* @author figo.zhu .
* @serial
* @since 2019年7月11日 下午3:47:31 .
*/
public class QueryMerBankConfigTask extends BaseTask<String> {
/**
* 日志.
*/
private MonitorLogger logger = MonitorLogger
.getLogger(QueryMerBankConfigTask.class);
/**
* merId .
*/
String merId;
/**
* tranType .
*/
String tranType;
/**
*
* @param merId .
* @param tranType .
*/
public QueryMerBankConfigTask(String merId,String tranType)
{
this.merId=merId;
this.tranType=tranType;
}
/**
* call .
* @return String .
* @exception Exception .
*/
@Override
public String call() throws Exception {
try {
long start = System.currentTimeMillis();
List<String> bankInstNoList = new APBusServiceImpl().getPayMode(merId, tranType);
this.listResult=bankInstNoList;
long end = System.currentTimeMillis();
System.out.println("getPayMode任务执行完毕,耗时(毫秒):" + (end - start));
logger.info(merId+","+tranType+"配置的支付机构:"+bankInstNoList);
return "1";
} catch (Exception e) {
logger.error("QueryMerBankConfigTask Exception:" + e.getStackTrace());
return "0";
}
}
}
4.调用(伪代码,自行调通)
boolean isFinished=FutureUtils.useFuture(tasks);
//所有任务结束,获取支付结果
if(isFinished)
{
bankInstNoListFor0001=queryMerBankConfigTaskFor0001!=null?queryMerBankConfigTaskFor0001.getListResult():bankInstNoListFor0001;
bankInstNoListFor0004=queryMerBankConfigTaskFor0004!=null?queryMerBankConfigTaskFor0004.getListResult():bankInstNoListFor0004;
bankInstNoListFor0005=queryMerBankConfigTaskFor0005!=null?queryMerBankConfigTaskFor0005.getListResult():bankInstNoListFor0005;
bankInstNoListFor0008=queryMerBankConfigTaskFor0008!=null?queryMerBankConfigTaskFor0008.getListResult():bankInstNoListFor0008;
whetherSupportItemFlag=queryItemFlagTask!=null?queryItemFlagTask.getResult():false;
fcBankInstNoList =queryAllForeignCardBanksTask!=null?queryAllForeignCardBanksTask.getListResult():fcBankInstNoList;
}
关键是调用executor.isTerminated()来判断所有线程是否已经执行完成。
if (executor.isTerminated()) {
long end = System.currentTimeMillis();
System.out.println("所有任务执行完毕,总耗时(毫秒):" + (end - start));
return true;
}