Akka系列(五):Java和Scala中的Future

三分青年發表於2019-01-28

隨著CPU的核數的增加,非同步程式設計模型在併發領域中的得到了越來越多的應用,由於Scala是一門函式式語言,天然的支援非同步程式設計模型,今天主要來看一下Java和Scala中的Futrue,帶你走入非同步程式設計的大門。

Future

很多同學可能會有疑問,Futrue跟非同步程式設計有什麼關係?從Future的表面意思是未來,一個Future物件可以看出一個將來得到的結果,這就和非同步執行的概念很像,你只管自己去執行,只要將最終的結果傳達給我就行,執行緒不必一直暫停等待結果,可以在具體非同步任務執行的時候去執行其他操作,舉個例子:

async work
async work

我們現在在執行做飯這麼一個任務,它需要煮飯,燒菜,擺置餐具等操作,如果我們通過非同步這種概念去執行這個任務,比如煮飯可能需要比較久的時間,但煮飯這個過程又不需要我們管理,我們可以利用這段時間去燒菜,燒菜過程中也可能有空閒時間,我們可以去擺置餐具,當電飯鍋通知我們飯燒好了,菜也燒好了,最後我們就可以開始吃飯了,所以說,上面的“煮飯 -> 飯”,“燒菜 -> 菜”都可以看成一個Future的過程。

Java中的Future

在Java的早期版本中,我們不能得到執行緒的執行結果,不管是繼承Thread類還是實現Runnable介面,都無法獲取執行緒的執行結果,所以我們只能線上程執行的run方法裡去做相應的一些業務邏輯操作,但隨著Java5的釋出,它為了我們帶來了Callable和Future介面,我們可以利用這兩個介面的特性來獲取執行緒的執行結果。

Callable介面

通俗的講,Callable介面也是一個執行緒執行類介面,那麼它跟Runnable介面有什麼區別呢?我們先來看看它們兩個的定義:

1.Callable介面:

@FunctionalInterface
public interface Callable<V> {
    /**
     * Computes a result, or throws an exception if unable to do so.
     *
     * @return computed result
     * @throws Exception if unable to compute a result
     */
    V call() throws Exception;
}複製程式碼

2.Runnable介面:

@FunctionalInterface
public interface Runnable {
    public abstract void run();
}複製程式碼

從上面的定義,我們可以看出,兩者最大的區別就是對應的執行方法是否有返回值。Callable介面中call方法具有返回值,這便是為什麼我們可以通過Callable介面來得到一個執行緒執行的返回值或者是異常資訊。

Future介面

上面說到既然Callable介面能返回執行緒執行的結果,那麼為什麼還需要Future介面呢?因為Callable介面執行的結果只是一個將來的結果值,我們若是需要得到具體的結果就必須利用Future介面,另外Callable介面需要委託ExecutorService的submit提交任務去執行,我們來看看它是如何定義的:

 <T> Future<T> submit(Callable<T> task);

 public <T> Future<T> submit(Callable<T> task) {
        if (task == null) throw new NullPointerException();
        RunnableFuture<T> ftask = newTaskFor(task);
        execute(ftask);
        return ftask;
    }複製程式碼

相關文章