多线程工具类ExecutorService的使用(所有任务执行完成后获取最终结果)

我们经常会有这种需求,比如APP首页,需要同时加载20多个接口,你怎么做?一个个按顺序调用接口吗?如果网络通畅还好,如果网络不好,你可能会让首页加载几分钟,用户体验肯定不好,那么我们就需要使用多线程来做。那假设其中有几个接口需要都执行完了,你才能继续执行后面的代码,怎么做?那这时候就需要 ExecutorService中的  Future submit(Callable 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 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  .
  * @since 2019年7月11日 下午3:37:57 .
  */
public abstract class BaseTask implements Callable {
	/**
	 * result list .
	 */
    List listResult;
    /**
     * result .
     */
    T result;
    /**
     * 
     * @return .
     */
	public List getListResult() {
		return listResult;
	}
    /**
     * 
     * @param listResult .
     */
	public void setListResult(List 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 {
	/**
	 * 日志.
	 */
	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 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;
            }

你可能感兴趣的:(java开发步步为营,java多线程,ExecutorService,java线程池)