Java多線程編程-4 設計模式之Future

1、什麼是future

Future是爲了解決同步調用必須等待調用執行結束後返回而設計的,future中文含義是“未來”,即調用方可以在未來某個時刻通過future來獲取調用結果。

通俗來講,future相當於一個票據,你拿着這個票據就可以在未來某個時點來兌現票據承諾的內容。

以訂蛋糕爲例:
第一種方式:你直接到店裏說我要買一個蛋糕,然後一直坐在店裏等直到蛋糕製作完成,不給你做好蛋糕你就一直等,然後你也幹不了別的事情(比如先去買個鮮花)。
第二種方式:你到店裏預定了一個蛋糕,工作人員給了你一張憑據,讓你先忙別的(如買鮮花,回家佈置一下),說做好了會通知你憑票取走蛋糕。
第三種方式:和第二種類似,只是你拿着票據後,買好鮮花後也沒別的事情,然後就一直在店裏催好了沒有(工作人員還可以忙別的事情),直到蛋糕店做好。

Future提供了一種異步調用的方式,等待被調用方返回處理結果(調用方可能同時處理多個任務),調用時立即返回,返回的是一個票據或者憑證,調用方在未來某個時點可以獲取調用結果。

2、java.util.concurrent.Future

public static void main(String[] args) throws Exception {
    Callable<String> task = () -> {
        TimeUnit.SECONDS.sleep(3);
        return "hello world";
    };
    ExecutorService executorService = Executors.newFixedThreadPool(1);
    Future<String> future = executorService.submit(task);
    System.out.println("do something");
    System.out.println(future.get());
}

上面的代碼創建了一個獲取字符串"hello world"的任務,需要花費3s的時間。
使用線程池提交該任務後立即返回一個future,程序繼續執行System.out.println(“do something”);打印出了"do something",等待3s後打印出了"hello world"。

那麼,Future是怎麼實現的呢?下面我們自己實現一個,原理都是一樣的

3、自己動手實現一個future設計模式

原理:
1、提交任務是立即返回一個票據,這裏是FutureResult
2、有一個線程池不斷的從隊列裏取出任務進行處理,當任務處理結束時通知

futureResult.setFuture()

3、當從FutureResult獲取結果,即調用getResult時,判斷是否處理完成,未完成則等待,直到flag=true

public T getResult() {
    while (!flag) {
         try {
             TimeUnit.MICROSECONDS.sleep(1);
         } catch (InterruptedException e) {
             e.printStackTrace();
         }
     }
     return future.getResult();
 }

完整代碼如下

public class FutureDIYExample {

    public static void main(String[] args) throws Exception {
        Callable<String> task = () -> {
            TimeUnit.SECONDS.sleep(3);
            return "hello world";
        };

        ThreadPoolService threadPoolService = new ThreadPoolService();
        Future<String> f = threadPoolService.submit(task);
        System.out.println("do something");
        System.out.println(f.getResult());

    }

    private interface Future<T> {
        T getResult();
    }

    /**
     * 執行結果
     * @param <T>
     */
    private static class FutureResult<T> implements Future<T> {
        private final Callable<T> task;

        private Future<T> future;

        private volatile boolean flag = false;

        public FutureResult(Callable<T> task) {
            this.task = task;
        }

        @Override
        public T getResult() {
            while (!flag) {
                try {
                    TimeUnit.MICROSECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            return future.getResult();
        }

        public void setFuture(Future<T> future) {
            this.future = future;
            this.flag = true;
        }

        public Callable<T> getTask() {
            return task;
        }
    }

    /**
     * 真正的執行結果
     * @param <T>
     */
    private static class FutureRealResult<T> implements Future<T> {
        private final T result;

        public FutureRealResult(T result) {
            this.result = result;
        }

        @Override
        public T getResult() {
            return result;
        }
    }

    private static class ThreadPoolService {

        private final LinkedList<FutureResult> queue = new LinkedList<>();

        private ExecutorService threadPool = Executors.newFixedThreadPool(1);

        public ThreadPoolService() {
            threadPool.execute(this::handleTask);
        }

        /**
         * 提交任務到隊列
         * @param task
         * @param <T>
         * @return
         */
        public <T> Future<T> submit(Callable<T> task) {
            FutureResult<T> future = new FutureResult<>(task);
            synchronized (queue) {
                this.queue.add(future);
                queue.notify();
            }
            return future;
        }

        /**
         * 處理隊列裏的任務
         */
        private void handleTask() {
            while (true) {
                FutureResult futureResult;
                synchronized (queue) {
                    if (queue.isEmpty()) {
                        try {
                            queue.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    futureResult = queue.removeFirst();
                }
                Callable task = futureResult.getTask();
                try {
                    futureResult.setFuture(new FutureRealResult(task.call()));
                    TimeUnit.SECONDS.sleep(1);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章