Future 解析與使用

Java 1.5開始, 提供了 CallableFuture, 經過它們能夠在任務執行完畢以後獲得任務執行結果.多線程

當須要調用幾個執行很慢的方法時, 可使用多線程一塊兒執行這幾個方法, 等全部方法執行完畢後獲得執行結果, 在進行別的處理.dom

Future 的主要方法ide

Future 接口主要包括 5 個方法:spa

clipboard.png

get() 方法能夠當任務結束後返回一個結果, 若是調用時, 工做尚未結束, 則會阻塞線程, 直到任務執行完畢.線程

get(long timeout,TimeUnit unit) 作多等待 timeout 的時間就會返回結果.3d

cancel(boolean mayInterruptIfRunning) 方法能夠用來中止一個任務.code

isDone() 方法判斷當前方法是否完成.blog

isCancel() 方法判斷當前方法是否取消.接口

Future 示例 demo遊戲

需求場景: 等早餐過程當中, 包子須要 3 秒, 涼菜須要 1 秒, 普通的多線程須要四秒才能完成. 先等涼菜, 再等包子, 由於等涼菜時, 普通多線程啓動 start() 方法, 執行 run() 中具體方法時, 沒有返回結果, 因此若是要等有返回結果, 必須是要1秒結束後才知道結果.

public static void main(String[] args) throws InterruptedException, ExecutionException {
        long start = System.currentTimeMillis();

        // 等涼菜 
        Callable ca1 = new Callable() {
            @Override
            public String call() throws Exception {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                return "涼菜準備完畢";
            }
        };
        FutureTask<String> ft1 = new FutureTask<String>(ca1);
        new Thread(ft1).start();

        // 等包子 -- 必需要等待返回的結果,因此要調用join方法
        Callable ca2 = new Callable() {

            @Override
            public Object call() throws Exception {
                try {
                    Thread.sleep(1000 * 3);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                return "包子準備完畢";
            }
        };
        FutureTask<String> ft2 = new FutureTask<String>(ca2);
        new Thread(ft2).start();

        System.out.println(ft1.get());
        System.out.println(ft2.get());

        long end = System.currentTimeMillis();
        System.out.println("準備完畢時間:" + (end - start));
    }

還有一個比較典型的例子就是設置超時時間:

//固定大小的線程池,同時只能接受5個任務
    static ExecutorService mExecutor = Executors.newFixedThreadPool(5);
    final static long timeout = 4 ;

    /**
     * 模擬在預約時間內獲取廣告信息
     * @throws InterruptedException
     */
    static void rederPageWithAd(final String pageTitle)  throws  InterruptedException{
        Future<String> f = mExecutor.submit(new Callable<String>() {
            @Override
            public String call() throws Exception {
                System.out.println("開始加載廣告信息");
                int randomTime = new Random().nextInt(5) + 1;//限制耗時不會出現0s,不會大於10s
                Thread.sleep(100 * 1000);
                System.out.println("正常加載廣告耗時:" + randomTime +"s");
                return pageTitle;
            }
        });

        String page;
        try {
            //在預計時間內等待
            System.out.println("預期任務執行完時間:" + timeout + "s");
            //page = f.get();
            page = f.get(timeout, TimeUnit.SECONDS);
        } catch (ExecutionException e) {
            page = "出現執行異常,顯示默認的廣告頁面";
        } catch (TimeoutException e) {
            page = "任務執行超時,顯示默認的廣告頁面";
            f.cancel(true);//取消沒有執行完的任務,設置爲ture說明任務能被中斷,不然執行中的任務要完成
        }
        System.out.println("成功加載廣告頁面:" + page);


    }


    public static void main(String[] args) {
        try {
            List<String> titleList = new ArrayList<String>();
            titleList.add("體育賽事");
            titleList.add("娛樂新聞");
            titleList.add("實時聚焦");
            titleList.add("國際諮詢");
            titleList.add("影視天下");
            titleList.add("遊戲風雲");
            for (String string : titleList) {
                rederPageWithAd(string);
            }

        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally{
            /**
             * 只有執行了shutdown方法,執行isTerminated纔有效。不然isTerminated一直爲ture
             */
            mExecutor.shutdown();
            while(true){
                if(mExecutor.isTerminated()){
                    System.out.println("全部任務都執行完了,關閉線程池");
                    break;
                }
            }
        }

    }

值得注意的是: 當主線程調用 Futureget 方法的時候會獲取到從線程中返回的結果數據. 若是在線程的執行過程當中發生了異常, get 會獲取到異常的信息.

相關文章
相關標籤/搜索