多執行緒並行執行,然後彙總結果

左邊520發表於2019-01-18

程式碼下載地址:https://download.csdn.net/download/hekf2010/10926623

很多時間,需要多執行緒並行處理,然後彙總處理結果,例如,因為請引數資料量非常大,所以只能分批查詢,然後將分批查詢的結果彙總到一個陣列中。

一、多執行緒類

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

/**
 * @param <H> 為被處理的資料型別
 * @param <T>返回資料型別
 */
public abstract class MultiThread<H,T>{
    private final ExecutorService exec; //執行緒池
    private final BlockingQueue<Future<T>> queue = new LinkedBlockingQueue<>();
    private final CountDownLatch startLock = new CountDownLatch(1); //啟動門,當所有執行緒就緒時呼叫countDown
    private final CountDownLatch endLock; //結束門
    private final List<H> listData;//被處理的資料
    
    
    /**
     * @param list list.size()為多少個執行緒處理,list裡面的H為被處理的資料
     */
    public MultiThread(List<H> list){
    	if(list!=null&&list.size()>0){
    		this.listData = list;
	        exec = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()); //建立執行緒池,執行緒池共有nThread個執行緒
	        endLock = new CountDownLatch(list.size());  //設定結束門計數器,當一個執行緒結束時呼叫countDown
    	}else{
    		listData = null;
    		exec = null;
    		endLock = null;
    	}
    }

    /**
     * 
     * @return 獲取每個執行緒處理結速的陣列
     * @throws InterruptedException
     * @throws ExecutionException
     */
    public List<T> getResult() throws InterruptedException, ExecutionException{
    	List<T> resultList = new ArrayList<>();
    	if(listData!=null&&listData.size()>0){
	    	int nThread = listData.size(); //執行緒數量
	        for(int i = 0; i < nThread; i++){
	            H data = listData.get(i);
	            Future<T> future = exec.submit(new Task(i,data){
	                @Override
	                public T execute(int currentThread,H data) {
	                    return outExecute(currentThread,data);
	                }
	            }); //將任務提交到執行緒池
	            queue.add(future); //將Future例項新增至佇列
	        }
	        startLock.countDown(); //所有任務新增完畢,啟動門計數器減1,這時計數器為0,所有新增的任務開始執行
	        endLock.await(); //主執行緒阻塞,直到所有執行緒執行完成
	        for(Future<T> future : queue) {
	            resultList.add(future.get());
	        }
	        exec.shutdown(); //關閉執行緒池
    	}
        return resultList;
    }
    /**
     * 每一個執行緒執行的功能,需要呼叫者來實現
     * @param currentThread 執行緒號
     * @param data 每個執行緒被處理的資料
     * @return T返回物件
     */
    public abstract T outExecute(int currentThread,H data);
    
    /**
     * 執行緒類
     */
    private abstract class Task implements Callable<T>{
        private int currentThread;//當前執行緒號
        private H data;
        public Task(int currentThread,H data){
            this.currentThread=currentThread;
            this.data=data;
        }
        @Override
        public T call() throws Exception {
            startLock.await(); //執行緒啟動後呼叫await,當前執行緒阻塞,只有啟動門計數器為0時當前執行緒才會往下執行
            T t =null;
            try{
                t = execute(currentThread,data);
            }finally{
                endLock.countDown(); //執行緒執行完畢,結束門計數器減1
            }
            return t;
        }

        /**
         * 每一個執行緒執行的功能
         * @param currentThread 執行緒號
         * @param data 每個執行緒被處理的資料
         * @return T返回物件
         */
        public abstract T execute(int currentThread,H data);
    }
}

二、引數類

public class ParamVo {

}

三、結果類

public class ResultVo {

}

四、測試


import java.util.ArrayList;
import java.util.List;

public class Test {

	public static void main(String[] args) {
		try {
			List<ParamVo> splitList = new ArrayList<ParamVo>();
			for(int i=0;i<100;i++){
				splitList.add(new ParamVo());
			}
			
			
			MultiThread<ParamVo,ResultVo> multiThread = new MultiThread<ParamVo,ResultVo>(splitList){
				@Override
				public ResultVo outExecute(int currentThread, ParamVo data) {
					System.out.println("當前執行緒號="+currentThread+" data="+data);
					return new ResultVo();
				}
			};
			List<ResultVo> list = multiThread.getResult();
			//獲取每一批次處理結果
			System.out.println("獲取處理結果........................");
			for(ResultVo vo:list){
				System.out.println(vo);
			}
		} catch (Exception e) {
			e.printStackTrace();
		} 
		

	}

}

 

相關文章