天天看點

Java線程(七):Callable和Future

       接着上一篇繼續并發包的學習,本篇說明的是Callable和Future,它倆很有意思的,一個産生結果,一個拿到結果。

       Callable接口類似于Runnable,從名字就可以看出來了,但是Runnable不會傳回結果,并且無法抛出傳回結果的異常,而Callable功能更強大一些,被線程執行後,可以傳回值,這個傳回值可以被Future拿到,也就是說,Future可以拿到異步執行任務的傳回值,下面來看一個簡單的例子:

       FutureTask實作了兩個接口,Runnable和Future,是以它既可以作為Runnable被線程執行,又可以作為Future得到Callable的傳回值,那麼這個組合的使用有什麼好處呢?假設有一個很耗時的傳回值需要計算,并且這個傳回值不是立刻需要的話,那麼就可以使用這個組合,用另一個線程去計算傳回值,而目前線程在使用這個傳回值之前可以做其它的操作,等到需要這個傳回值時,再通過Future得到,豈不美哉!這裡有一個Future模式的介紹:http://openhome.cc/Gossip/DesignPattern/FuturePattern.htm。

       下面來看另一種方式使用Callable和Future,通過ExecutorService的submit方法執行Callable,并傳回Future,代碼如下:

       代碼是不是簡化了很多,ExecutorService繼承自Executor,它的目的是為我們管理Thread對象,進而簡化并發程式設計,Executor使我們無需顯示的去管理線程的生命周期,是JDK 5之後啟動任務的首選方式。

       執行多個帶傳回值的任務,并取得多個傳回值,代碼如下:

       其實也可以不使用CompletionService,可以先建立一個裝Future類型的集合,用Executor送出的任務傳回值添加到集合中,最後周遊集合取出資料,代碼略。更新于2016-02-05,評論中就這個說法引發了讨論,其實是我沒有講清楚,抱歉。這裡再闡述一下:送出到CompletionService中的Future是按照完成的順序排列的,這種做法中Future是按照添加的順序排列的。是以這兩種方式的差別就像評論中fishjam所描述的那樣。