Promise模式

Promise 模式

簡介

Promise 模式是一種異步編程模式,使用它我們可以先開始一個任務, 並能立即獲取這個任務的執行結果的憑證對象, 而不需要等待任務執行完畢,就可以繼續執行其他操作. 當需要執行結果的時候,可以通過憑證對象,可以調用相應方法來獲取.

這樣操作的好處就是: 避免了不必要的等待, 增強系統的併發性.

成員

  1. 任務執行器
  2. 憑證對象
  3. 自定義任務
  4. 任務結果對象

實例實現

  • 模擬任務 - MyTask
public class MyTask implements Callable<MyPromiseResult> {

    private String context;

    public MyTask(String context) {
        this.context = context;
    }

    @Override
    public MyPromiseResult call() throws Exception {

        Random random = new Random();
        int workTime = random.nextInt(5 * 1000);

        MyPromiseResult result = new MyPromiseResult(workTime, context);
        result.setTaskStartTime();

        Thread.sleep(workTime);// 模擬工作

        result.setTaskEndTime();

        return result;
    }

}
  • 憑證對象使用: FutureTask
  • 憑證返回結果: MyPromiseResult

public class MyPromiseResult {
    // 任務開始時間
    private long taskStartTime;
    // 任務結束時間
    private long taskEndTime;
    //  工作耗時間
    private final int workTime;
    // 上下文任務名稱
    private final String taskName ;

    public MyPromiseResult (int workTime, final String taskName) {
        this.workTime = workTime;
        this.taskName = taskName;
    }

    public void setTaskStartTime() {
        this.taskStartTime = System.currentTimeMillis();
    }

    public void setTaskEndTime() {
        this.taskEndTime = System.currentTimeMillis();
    }

    public long getTaskStartTime() {
        return this.taskStartTime;
    }

    public long getTaskEndTime() {
        return this.taskEndTime;
    }


    public String getTaskName() {
        return taskName;
    }

    public void print() {
        if (taskEndTime > 0) { // 代表完成
            System.out.println("完成任務名稱:" + taskName +"...開始時間" + taskStartTime +"...耗時間:"
                    + workTime);
        }
    }

}
  • 測試類

public class PromiseTester {
    // 任務執行器
    static ThreadPoolExecutor threadExecutor = null;

    static {
        threadExecutor = new ThreadPoolExecutor(2, Runtime.getRuntime().availableProcessors() * 2 , 
                60, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(10),
                new ThreadFactory() {

                    @Override
                    public Thread newThread(Runnable r) {
                        Thread t = new Thread(r);
                        t.setDaemon(true);
                        return t;
                    }
                });
    }

    public static void main(String args[]) throws InterruptedException, ExecutionException {
        test();
    }

    /**
     * 
     *  測試有一個任務它由10個子任務構成, 每個子任務相互獨立
     *  只有10個子任務都完成,這個任務纔算完成 
     * @throws InterruptedException
     * @throws ExecutionException
     */
    public static void test() throws InterruptedException, ExecutionException {
        ConcurrentMap<String, FutureTask<MyPromiseResult>>  taskMap = new ConcurrentHashMap<String, 
                FutureTask<MyPromiseResult>>();

        for (int i = 0; i < 10; i ++) {
            String name = "task-" + i;
            FutureTask<MyPromiseResult> futureTask = PromiseTester.execute(name);
            taskMap.put(name, futureTask);
        }

        FutureTask<MyPromiseResult> task = null;
        MyPromiseResult myPromiseResult;

        // 輪詢判斷任務是否完成

        for (;;) {

            if (!taskMap.isEmpty()) {

                Iterator<String> iterator = taskMap.keySet().iterator();

                while (iterator.hasNext()) {
                    task = taskMap.get(iterator.next());
                    if (null != task && task.isDone()) {
                        myPromiseResult = task.get();
                        myPromiseResult.print();

                        taskMap.remove(myPromiseResult.getTaskName());
                        iterator = taskMap.keySet().iterator();
                    }
                }

            } else {
                break;
            }

            Thread.sleep(10);

        }

        System.out.println("############所有任務完成###############");

    }

    /**
     * 異步提交,並獲取憑證對象
     * 
     * @param context
     * @return
     */
    public static FutureTask<MyPromiseResult> execute(String context) {
        FutureTask<MyPromiseResult> futureTask = new FutureTask<MyPromiseResult>(new MyTask(context));

        threadExecutor.execute(futureTask);

        return futureTask;
    }


}
  • 測試結果
完成任務名稱:task-0...開始時間1471786979890...耗時間:352
完成任務名稱:task-1...開始時間1471786979890...耗時間:1526
完成任務名稱:task-3...開始時間1471786981416...耗時間:1835
完成任務名稱:task-2...開始時間1471786980242...耗時間:4534
完成任務名稱:task-4...開始時間1471786983251...耗時間:3672
完成任務名稱:task-5...開始時間1471786984776...耗時間:3908
完成任務名稱:task-6...開始時間1471786986923...耗時間:2037
完成任務名稱:task-7...開始時間1471786988684...耗時間:2948
完成任務名稱:task-9...開始時間1471786991632...耗時間:238
完成任務名稱:task-8...開始時間1471786988960...耗時間:3923
############所有任務完成###############
發佈了49 篇原創文章 · 獲贊 13 · 訪問量 12萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章