Java5執行緒併發庫之CALLABLE(可呼叫的,任務)&FUTURE(未來,期望的)

NO IMAGE
1 Star2 Stars3 Stars4 Stars5 Stars 給文章打分!
Loading...

Callable(可呼叫的,任務)&Future(未來,期望的)

接下來我們講Callable和Future,這個Callable和Future的作用就是,我們程式啟動一個執行緒,然後那個執行緒執行完了以後呢,它可以給我們返回結果。我們可以去獲得這個執行緒執行完了以後的結果。以下通過程式碼來看一看它們的效果:

提交單個Callable執行緒任務,獲得它的返回值

執行緒池不用執行緒池的void execute(Runnable command)方法來執行任務,而是用<T> Future<T> submit(Callable<T> task)  方法來提交任務,這個方法專門用於提交一個有返回值的任務。這個任務用Callable物件表示,重寫它裡面的call方法,就可以把程式碼放到call方法裡面執行,並返回結果。結果的型別是通過泛型宣告的。這個任務提交以後會有一個結果,這個結果用Future型別的變數接收。我們可以通過future的get()方法,獲取到執行緒返回的結果。

public class CallableAndFuture {

    /**

     * @param args

     */

    public static void main(String[] args) {

        ExecutorService threadPool = Executors.newSingleThreadExecutor();

        Future<String> future = threadPool.submit(new Callable<String>() {

            public String call() throws Exception {

                Thread.sleep(2000);

                return “hello”;

            };

        });

        System.out.println(“等待結果”);

        try {

            System.out.println(“拿到結果:” future.get());

        } catch (InterruptedException e) {

            e.printStackTrace();

        } catch (Exception e) {

            e.printStackTrace();

        }

    }

}

這個只是目前還不知道有什麼使用場景。我有一個任務,交給你去執行,執行完了我確實可以拿到結果,但是,我什麼時候能夠拿到結果呢?我過一會兒就問一下,有沒有結果。這對我來說就沒有什麼意思,那我還不如不起一個執行緒,我直接呼叫一個方法,不開子執行緒,然後執行,執行完了我得到結果。如果說我啟動一個執行緒的意思就是說,好,你去幹,幹了以後呢,我忙我的,你忙你的,結果出來了,你告訴我,如果我一天到晚去問你,我還幹不幹事了呢?那我還不如直接呼叫你,沒必要搞一個新執行緒。

簡單的說,就是有一個Callable的任務,這個任務會返回結果,返回的結果用Future來拿,當結果返回了之後,Future就可以拿到結果了,當future還沒有拿到結果的時候,future.get()會一直在那裡等,既然是一直在那裡等,程式碼沒有辦法往下執行,那我乾脆呼叫一個方法,也是一樣的,反正也是幹不了活,都得等執行完,拿到結果。

好,那沒有一種可能就是,我不想等,我跑過來看一下結果來了沒有,沒來的話,我又去忙別的,過了一會兒,我又來看結果來了沒有,那麼這時候我們可以看一下api文件,Future物件上有沒有一種方法可以,我先去看有沒有結果,如果沒有結果,我就去忙別的,而不是必須在那裡等。我們看到有一個get的過載方法V get(long timeout, TimeUnit unit),這個方法可以設定等待的時間。如果它是說超過等待的時間沒有返回結果,我就可以去做別的事,這還比較好。如果超過時間沒有結果就拋異常的話,這就受不了了。結果它是拋的一個Timeout異常。這就不行了,我的本意事沒有就沒有唄,沒有我就去幹別的事,結果呢,它非要去跟人家打一架,大的頭破血流都報紅了。這樣,感覺就沒有什麼太大的意義。

CompletionService提交一組Callable任務,並獲得它們的返回值

接下來我們再看一種應用CompletionService,就是我一下就提交一組Callable任務,然後我就用它的返回值型別CompletionService的take方法去取,凡是只要有一個任務執行完了,我就會得到結果。哪個任務先執行完,就先拿到哪個任務的結果。如果有10個任務,就要拿10次結果。它的泛型就是任務的返回值的型別。我們用CompletionService的子類ExecutorCompletionService來建立物件,這個建立的物件它不是一個執行緒池,它執行的時候,比如它有10個任務需要執行的時候,它是不是要交給執行緒池來執行呀。所以呢,我們還要給它的構造方法傳入一個執行緒池物件。

ExecutorService threadPool2 = Executors.newFixedThreadPool(10);

        CompletionService<Integer> completionService = new ExecutorCompletionService<Integer>(threadPool2);

        for (int i = 1; i <= 10; i ) {

            final int seq = i;

            completionService.submit(new Callable<Integer>() {

                @Override

                public Integer call() throws Exception {

                    Thread.sleep(new Random().nextInt(5000));

                    return seq;

                }

            });

        }

        for (int i = 0; i < 10; i ) {

            try {

                System.out.println(completionService.take().get());

            } catch (InterruptedException e) {

                // TODO Auto-generated catch block

                e.printStackTrace();

            } catch (ExecutionException e) {

                // TODO Auto-generated catch block

                e.printStackTrace();

            }

        }


(adsbygoogle = window.adsbygoogle || []).push({});

function googleAdJSAtOnload() {
var element = document.createElement(“script”);
element.src = “//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js”;
element.async = true;
document.body.appendChild(element);
}
if (window.addEventListener) {
window.addEventListener(“load”, googleAdJSAtOnload, false);
} else if (window.attachEvent) {
window.attachEvent(“onload”, googleAdJSAtOnload);
} else {
window.onload = googleAdJSAtOnload;
}

程式語言 最新文章