java異步計算Future的使用(轉)


從jdk1.5開始我們可以利用Future來跟蹤異步計算的結果。在此之前主線程要想獲得工作線程(異步計算線程)的結果是比較麻煩的事情,需要我們進行特殊的程序結構設計,比較繁瑣而且容易出錯。有了Future我們就可以設計出比較優雅的異步計算程序結構模型:根據分而治之的思想,我們可以把異步計算的線程按照職責分為3類:

1. 異步計算的發起線程(控制線程):負責異步計算任務的分解和發起,把分解好的任務交給異步計算的work線程去執行,發起異步計算后,發起線程可以獲得Futrue的集合,從而可以跟蹤異步計算結果

2. 異步計算work線程:負責具體的計算任務

3. 異步計算結果收集線程:從發起線程那里獲得Future的集合,並負責監控Future的狀態,根據Future的狀態來處理異步計算的結果。

 

以下是我根據上述想法寫的一個例子:

package com.chengxuyuanzhilu.two;

import java.util.List;
import java.util.concurrent.Future;


public class OutputResult implements Runnable {

    private FutureContext<String> context;
    
    public void setFutureContext(FutureContext<String> context){
        this.context = context;
    }
    
    @Override
    public void run() {
        System.out.println("start to output result:");
        List<Future<String>> list = this.context.getFutureList();
        
        for (Future<String> future : list) {
            this.outputResultFromFuture(future);
        }
        System.out.println("finish to output result.");
    }
    
    private void outputResultFromFuture(Future<String> future){
        try {
            while (true) {
                if(future.isDone() && !future.isCancelled()){
                    System.out.println("Future: " + future + ",Result:" + future.get());
                    break;
                }else{
                    Thread.sleep(1000);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        };
    }

}
package com.chengxuyuanzhilu.two;

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

public class FutureContext<T> {
    private List<Future<T>> futureList = new ArrayList<>();
    
    public  void addFuture(Future<T> future){
        this.futureList.add(future);
    }
    
    public List<Future<T>> getFutureList(){
        return this.futureList;
    }
}
package com.chengxuyuanzhilu.two;

import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class AsyncController {
    //線程池
    private ExecutorService executorService;
    
    //保存異步計算的Future
    private FutureContext<String> context;
    
    public AsyncController() {
        //創建一個固定大小的線程池
        this.executorService = Executors.newFixedThreadPool(100);
        this.context = new FutureContext<>();
    }
    
    public static void main(String[] args) {
        //啟動異步計算
        AsyncController controller = new AsyncController();
        controller.startAsycCompution();
        
        //啟動異步計算結果輸出線程,該線程掃描異步計算Futrue的狀態,如果已經完成,則輸出異步計算結果
        OutputResult output = new OutputResult();
        output.setFutureContext(controller.getFutureContext());
        Thread resultThread = new Thread(output);
        resultThread.start();
    }
    
    public FutureContext<String> getFutureContext(){
        return this.context;
    }
    
    public void startAsycCompution(){
        /**
         * 開啟100個異步計算,每個異步計算線程隨機sleep幾秒來模擬計算耗時
         */
        final Random random = new Random();
        
        for (int i = 0; i < 100; i++) {
            Future<String> future = this.executorService.submit(
                    new Callable<String>(){

                        @Override
                        public String call() throws Exception {
                            int randomInt = random.nextInt(10);
                            Thread.sleep(randomInt * 1000);
                            return "" + randomInt;
                        }
                        
                    });
            //每個異步計算的結果 存放在context中
            this.context.addFuture(future);
        }
    }

}

源碼下載地址:http://pan.baidu.com/s/1c1uuq5M


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM