簡短的回答
不,這不是更自然的CompletableFuture.supplyAsync
使用Callable
,而不是Supplier
。這個論點幾乎完全是關於語義的,所以如果你之後仍然不確定,那就沒關係。
龍答案
的Callable
和Supplier
功能接口/ SAM類型在功能上幾乎相等(原諒雙關語),但其來源和用途不同。
Callable
被創建爲java.util.concurrent
包的一部分。這個包來自Java 8中關於lambda表達式的巨大變化,最初集中在幫助您編寫併發代碼的一系列工具上,而不會偏離經典的動態多線程模型。
Callable
的主要用途是抽象可以在不同線程中執行並返回結果的動作。從Callable
的Javadoc中:
的Callable
接口類似於Runnable
,在兩者都 設計用於一個其實例可能受 另一個線程執行。
Supplier
被作爲java.util.function
包的一部分創建的。該包作爲Java 8上述更改的組成部分。它提供了可以由lambda表達式和方法引用定位的常用函數類型。
一種這樣的類型是沒有參數返回結果的函數(即提供某種類型函數或函數)。
那麼爲什麼Supplier
而不是Callable
?
CompletableFuture
是添加到由在Java中8的上述變化的啓發,允許顯影劑以構建在功能,隱含並行方式他的代碼java.util.concurrent
包的一部分,而不是在它明確地處理併發。
它的supplyAsync
方法需要一種方法來提供特定類型的結果,並且對結果更感興趣,而不是爲了達到這個結果而採取的行動。它也不一定關心異常完成(另請參閱下面的...段落)。
但是,如果Runnable
用於無參數,無結果功能接口,不應使用Callable
用於無參數,單結果功能接口?
不一定。
對於沒有參數且不返回結果(因此完全通過外部上下文中的副作用操作)的函數的抽象不包括在java.util.function
中。這意味着(有些惱人地)Runnable
被用在任何需要這種功能接口的地方。
那麼Callable.call()
可以拋出的支票Exception
怎麼辦?
這是Callable
和Supplier
之間預期語義差異的一個小符號。
A Callable
是一個動作,可以在另一個線程中執行,並允許您檢查其副作用的執行結果。如果一切順利,您會得到特定類型的結果,但由於在執行某些操作時(特別是在多線程環境中)可能會出現異常情況,因此您可能還需要定義和處理這些異常情況。
另一方面,A Supplier
是您依賴於提供某種類型的對象的函數。作爲Supplier
的直接消費者,例外情況不一定是您的責任。這是因爲:
- ...功能接口通常用於在創建或變異數據,以及處理
Exception
可以均是一個獨立的階段,多階段過程定義一個特定的階段,如果你不在乎
- ...明確處理
Exception
小號顯著減少的功能接口,Lambda表達式和方法表達能力引用
因爲他們剛剛從C#,這通常命名爲'行動<>'和'不同Func <>'接口,它們完成相同的工作,但不會讓程序員感到困惑。所以他們擴大了具有相同簽名但不同名稱的方法的功能接口。他們可能認爲這會幫助程序員提供一個合作的心理模型,但它不會:這只是一個小小的PITA。 – davidbak