Java多線程帶返回值的Callable接口

Java多線程帶返回值的Callable接口java

在面試的時候,有時候是否是會遇到面試會問你,Java中實現多線程的方式有幾種?你知道嗎?你知道Java中有能夠返回值的線程嗎?在具體的用法你知道嗎?若是兩個線程同時來調用同一個計算對象,計算對象的call方法會被調用幾回你知道嗎?若是這些你知道,那麼凱哥(凱哥Java:kaigejava)恭喜你,本文你能夠不用看了。若是你不知道這些,那麼凱哥一樣要恭喜你,看了凱哥這篇文章以後,就知道這些了。來看看這篇文章咱們能學到什麼面試

本節主要內容設計模式

一:三種獲取多線程的的寫法多線程

二:分析第三種寫法的思想思路-使用了適配器模式ide

三:第三種方法怎麼使用spa

四:多個線程調用同一個futrueTask後,future的call方法會被執行幾回?線程

一:三種獲取線程的寫法

咱們已經知道Java中經常使用的兩種線程實現方式:分別是繼承Thread類和實現Runnable接口。設計

以下圖:3d

0glTN2uKb3I


從上圖中,咱們能夠看到,第三種實現Callable接口的線程,並且還帶有返回值的。咱們來對比下實現Runnable和實現Callable接口的兩種方式不一樣點:orm

1:須要實現的方法名稱不同:一個run方法,一個call方法

2:返回值不一樣:一個void無返回值,一個帶有返回值的。其中返回值的類型和泛型V是一致的。

3:異常:一個無需拋出異常,一個須要拋出異常。在後面使用場景中,凱哥會講解到的

二:callable接口的設計思路?

咱們先來看看Thread類:這個類是Java中獲取線的對象。通常咱們獲取並啓動線程調用的是start方。從JDK的API中,咱們能夠看到,start方法是JVM調用的

0glTN3MiRrU


再來看看常寫的方法:

Thread t1 = new Thread();

t1.start();

咱們來看看其構造器:

0glTN3kmF04


三個構造器:無參構造器、一個參數構造器和兩個參數構造器。可是就沒有咱們Callable做爲參數的構造器。那麼,咱們想要獲取到線程,經過callable怎麼獲取呢 ?

0glTN4DJ0W8


就拿凱哥剛到帝都找房子的案例來講吧。凱哥剛到帝都人生地不熟的,想要找房子怎麼辦呢?

房東有房子,凱哥想要找房子,那麼這兩個原本沒有直接聯繫的經過房屋中介公司就產生了關係。凱哥要想找到房子,先要找到房屋中介公司,而後房屋中介公司又有房東的聯繫方式,而後凱哥就經過中介公司租到房東的房子了(中介公司從中間收取手續費)。這個現實案例我想你們都遇到過吧。

好了,咱們經過上面案例在回到Thread類和Callable類來看,這兩個對象之間有沒有中間商呢?

0glTN4VUBAe


從上圖中咱們發現,Threa的有參構造都是Runnable接口的。那麼,有沒有一個類既實現了Runnable接口又實現了Callable接口呢?若是有這樣的一個類存在的話,callable就與Thread類產生了關係,就可使用了。咱們來看看Runnable接口的API吧

0glTN4sCo64


咱們能夠已知的子類有個RunnableFuture<V>。這個接口的形式和咱們Callable接口的形式很像啊,以下圖:

0glTN7P46Iy


咱們從上圖對比中能夠看到,兩個接口中的V都是方法返回值的類型。那麼Callable和Thread兩個類之間的橋樑就是這個類(RunnableFuture)或者是這個類的子類呢?咱們接着來看看這個對象的子類。

0glTN7xODUu


其中SwingWorker這個咱們不用看。這個是圖形化的Swing相關的。咱們不用,那麼咱們就來看看FutureTask這個類:

從這個類中,咱們能夠看到其實現了Runnable接口,在構造器中,咱們能夠看到:

FutureTask(Callable<V> callable)

建立一個 FutureTask ,它將在運行時執行給定的 Callable 。

以下圖:

0glTN8UkQLI


這個類是否是既有Callable接口又有Runnable接口了?這個就是咱們的中間類。

因此,咱們經過上面分析就能夠獲得下圖的關係:

0glTN8waUbI


這種就是設計模式中的適配器模式(PS:在後面,凱哥會從新分享23種設計模式的)。在Java中的中間商是不會賺取差價的,放心。O(∩_∩)O

三:callable怎麼使用及怎麼獲取返回值

知道了Callable的設計思路以後,那麼咱們怎麼來使用呢?

步驟:

1:一樣建立一個類實現Callable接口;

2:經過futureTask類使用其傳遞Callable接口做爲參數的有參構造方法;

3:使用thread的有參構造;

4:t1.start()啓動線程

5:啓動線程後,經過futureTask.get()方法獲取到線程的返回值。

以下圖:

0glTN9K7rkW


咱們來查看運行結果:

0glTN9gVKeu


進入了callable接口且獲取到了返回值:1024.說明callable的使用正確了。

須要注意:futrueTask.get()方法放到最後,這樣就不會影響主線程了。若是get方法放在前面的話,會形成主線程阻塞,等到futrueTask運行完成以後,才繼續執行本身的邏輯。這樣就失去了開啓線程的意義了!!!

四:多個線程同時調用結果

0glTNAxXGEq


咱們能夠看到t1和t2都start了,說明兩個線程都啓動了。並且都是用的是同一個futureTask對象。問題:MyThread3中的call方法會被調用幾回呢?

wx.jpg

相關文章
相關標籤/搜索