03.01 詳解第三種創建線程的方式-Callable接口

相信大多數學過多線程的同學都知道創建線程常見的有三種方式,一種是繼承Thread類,一種是實現Runnable接口,最後一種就是Callable,今天主要是對最後不常見的Callable方式進行介紹。

一、為什麼要Callable接口

既然有了前面兩種接口,為什麼還需要第三種呢?這是因為前兩種方式存在著幾種缺陷,我們先來看看前面兩種實現的方式,然後再來揭曉:

詳解第三種創建線程的方式-Callable接口

現在我們觀察裡面的run方法,返回的都是void,也就是說這兩種方式都不能返回處理後的結構。但是Callable接口的出現可以有效地解決這一問題。答案很簡單。現在我們來看看如何實現。

二、Callable接口的使用

1、創建線程

我們先來創建一個實現了Callable接口的線程。

詳解第三種創建線程的方式-Callable接口

如何去使用呢?像前面兩個一樣嗎?這裡面會稍微有點麻煩的地方,我們建好了,接下來就是使用了,不過我們直接介紹使用的話,不那麼容易理解,所以我們這次反著來。

2、線程使用

我們先來看Thread的構造方法:

詳解第三種創建線程的方式-Callable接口

這個源碼我摘自jdk1.8,一共列舉了9個構造函數,但是仔細觀察就能發現,沒有一個構造方法可以傳入Callable接口,這也就意味著不能根據之前那種簡單的方式來創建線程。這時候怎麼辦呢?那就得換一種思考方式。

既然線程能有返回值,不知道是否可以聯想到一個函數式接口Future,我們以此為基點進行查詢:

詳解第三種創建線程的方式-Callable接口

從上面的代碼我們可以看出FutureTask這個實現類,既有了Runnable線程的特性,也有了Future可返回函數的特性。因此我們就可以使用FutureTask這個類來實現Callable的使用。

詳解第三種創建線程的方式-Callable接口

這就是一個最基本的使用方法。當然Future還提供了很多其他的方法:

(1)cancel方法用來取消任務,如果取消任務成功則返回true,如果取消任務失敗則返回false。

參數mayInterruptIfRunning表示是否允許取消正在執行卻沒有執行完畢的任務,如果設置true,則表示可以取消正在執行過程中的任務。如果任務已經完成,則無論mayInterruptIfRunning為true還是false,此方法肯定返回false,即如果取消已經完成的任務會返回false;

如果任務正在執行,若mayInterruptIfRunning設置為true,則返回true,

若mayInterruptIfRunning設置為false,則返回false;

如果任務還沒有執行,則無論mayInterruptIfRunning為true還是false,肯定返回true。

(2)isCancelled方法表示任務是否被取消成功,如果在任務正常完成前被取消成功,則返回 true。

(3)isDone方法表示任務是否已經完成,若任務完成,則返回true;

(4)get()方法用來獲取執行結果,這個方法會產生阻塞,會一直等到任務執行完畢才返回;

(5)get(long timeout, TimeUnit unit)用來獲取執行結果,如果在指定時間內,還沒獲取到結果,就直接返回null。

基本上就是這樣。其實經常會配合著ExecutorService來使用,現在我們舉個例子來看一下:

詳解第三種創建線程的方式-Callable接口

常見的用法就是這麼兩個。因為Callable是接口,所以分析源碼並沒有什麼意義。OK,針對這個Callable接口的介紹,就先到這裡。

如有問題還請批評指正。


分享到:


相關文章: