J.U.C 組件之 FutureTask

Futrue Task 是 J.U.C 的組件 , 但不是 AQS 的子類

Futrue Task

我們知道在 Java 中 , 創(chuàng)建一個(gè)線程有兩種方法 , 一種是直接繼承Thread , 另外一種是實(shí)現(xiàn) Runable接口 , 但是這兩種方式都有一個(gè)共同的缺陷是 , 它們?cè)趫?zhí)行為任務(wù)時(shí), 都無(wú)法獲取到任務(wù)的結(jié)果 . 在 jdk 1.5 之后 , 提供了CallableFuture , 通過它倆可以在任務(wù)執(zhí)行修改完畢之后得到任務(wù)的執(zhí)行結(jié)果 .

Callable 和 Runable 接口對(duì)比

Runable 比較簡(jiǎn)單, 它是一個(gè)接口, 而且只有一個(gè)方法 run() , Callable 也較為簡(jiǎn)單, 不同的是 它是一個(gè)泛型的接口 , 它有一個(gè) call()函數(shù) , 這個(gè)函數(shù)的返回類型就是我們創(chuàng)建 Callable傳進(jìn)去的類型, 兩者比較相比, Callable 功能較強(qiáng)大一些, 主要是其被線程執(zhí)行后有返回值, 并且能拋出異常 .

Future接口

對(duì)于 Callable 或者 Future 的任務(wù) , Futrue 可以對(duì)其取消 , 查詢其任務(wù)是否被取消, 查詢?nèi)蝿?wù)是否完成, 已經(jīng)獲取結(jié)果等 . 通常線程都是屬于異步計(jì)算模型的, 你不可嫩從別的線程得到方法的返回值 , 這個(gè)時(shí)候 Futrue 就派上用場(chǎng)了 , Futrue 可以監(jiān)視目標(biāo)線程調(diào)用 call() 的情況, 當(dāng)你調(diào)用 Futrue get() 方法的時(shí)候 , 就可以獲得它的結(jié)果 , 這個(gè)時(shí)候通常線程不會(huì)直接完成, 當(dāng)前線程就開始阻塞 , 直到 call()方法返回結(jié)果, 線程才繼續(xù)執(zhí)行 . 總之就是, Futrue 可以得到別的線程任務(wù)方法的返回值 .

Futrue Task 類

其父類是 RunableFutrue , 而 Runable Futrue 繼承了 Runable 和 Futrue 這兩個(gè)接口 . 所以 Futrue Task 最后執(zhí)行的也是 Callable 類型的任務(wù) .

/**
 * A {@link Future} that is {@link Runnable}. Successful execution of
 * the {@code run} method causes completion of the {@code Future}
 * and allows access to its results.
 * @see FutureTask
 * @see Executor
 * @since 1.6
 * @author Doug Lea
 * @param <V> The result type returned by this Future's {@code get} method
 */
public interface RunnableFuture<V> extends Runnable, Future<V> {
    // 繼承了 Runnable 和 Future
    /**
     * Sets this Future to the result of its computation
     * unless it has been cancelled.
     */
    void run();
}

如果構(gòu)造函數(shù)數(shù) Runable 的話 ,它或轉(zhuǎn)換成 Callable 類型. Futrue Task 實(shí)現(xiàn)了 兩個(gè)接口 RunableFutrue , 所以它既可以作為Runable被線程執(zhí)行 , 又可以作為 Futrue 得到 Callable 的返回值 . 這兩個(gè)接口的組合有什么優(yōu)點(diǎn)呢 , 比如說(shuō) , 有一個(gè)很費(fèi)時(shí)邏輯需要計(jì)算, 并返回結(jié)果, 同時(shí)這個(gè)值又不是馬上需要, 就可以使用它, 用另外一個(gè)線程去就按返回值, 而當(dāng)前現(xiàn)在在使用這個(gè)返回值之前可以做其他的操作,等到需要這個(gè)返回值的時(shí)候, 再通過 Future得到 .

代碼實(shí)例

  • Future 代碼示例
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

@Slf4j
public class FutureExample {

    // 定義一個(gè)Callable的任務(wù) MyCallable , 這里返回一個(gè)String 類型
    static class MyCallable implements Callable<String> {

        @Override
        public String call() throws Exception {
            // 假如 在這個(gè)callable 做一些事情需要比較長(zhǎng)時(shí)間 , 咱們讓線程 sleep 5s
            log.info("do something in callable");
            Thread.sleep(5000);
            // 任務(wù)完成了 返回 Done
            return "Done";
        }
    }

    public static void main(String[] args) throws Exception {

        // 使用Future和 Callable 的時(shí)候一般是通過線程池類調(diào)用的 . 在這里 申明一個(gè)線程池

        ExecutorService executorService = Executors.newCachedThreadPool();

        // 讓線程池直接提交該任務(wù) , 返回任務(wù)結(jié)果
        // 這樣就相當(dāng)于用 Future 接收了另外一個(gè)線程任務(wù)計(jì)算的結(jié)果
        Future<String> future = executorService.submit(new MyCallable());
        log.info("do something in main");
        Thread.sleep(1000);
        // 獲取之前的任務(wù)返回了什么結(jié)果
        String result = future.get();
        log.info("result:{}", result);
    }
}
  • Future Task 示例
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;

@Slf4j
public class FutureTaskExample {

    public static void main(String[] args) throws Exception {
        FutureTask<String> futureTask = new FutureTask<String>(new Callable<String>() {
            @Override
            public String call() throws Exception {
                log.info("do something in callable");
                Thread.sleep(5000);
                return "Done";
            }
        });

        new Thread(futureTask).start();
        log.info("do something in main");
        Thread.sleep(1000);
        String result = futureTask.get();
        log.info("result:{}", result);
    }
}

上兩示例代碼結(jié)果輸出 如下圖

輸出

總結(jié)

FutureTask 是將 FutureCallable 相關(guān)的東西都結(jié)合在一起了, 所以在他們?nèi)齻€(gè)之間 , 使用 FutureTask 就可以解決你想做的事情 . 如果在Java 程序中, 如果你想起一個(gè)線程去做一些事情的時(shí)候, 并且你還希望獲得線程的結(jié)果已經(jīng)它是否正常執(zhí)行, 就可以使用 FutureTask .

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子鳞贷,更是在濱河造成了極大的恐慌菠赚,老刑警劉巖探橱,帶你破解...
    沈念sama閱讀 219,039評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件销凑,死亡現(xiàn)場(chǎng)離奇詭異溉苛,居然都是意外死亡酬滤,警方通過查閱死者的電腦和手機(jī)签餐,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)盯串,“玉大人氯檐,你說(shuō)我怎么就攤上這事√迥螅” “怎么了冠摄?”我有些...
    開封第一講書人閱讀 165,417評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵糯崎,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我河泳,道長(zhǎng)沃呢,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,868評(píng)論 1 295
  • 正文 為了忘掉前任拆挥,我火速辦了婚禮薄霜,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘纸兔。我一直安慰自己惰瓜,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,892評(píng)論 6 392
  • 文/花漫 我一把揭開白布汉矿。 她就那樣靜靜地躺著崎坊,像睡著了一般。 火紅的嫁衣襯著肌膚如雪洲拇。 梳的紋絲不亂的頭發(fā)上奈揍,一...
    開封第一講書人閱讀 51,692評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音呻待,去河邊找鬼打月。 笑死,一個(gè)胖子當(dāng)著我的面吹牛蚕捉,可吹牛的內(nèi)容都是我干的奏篙。 我是一名探鬼主播,決...
    沈念sama閱讀 40,416評(píng)論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼迫淹,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼秘通!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起敛熬,我...
    開封第一講書人閱讀 39,326評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤肺稀,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后应民,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體话原,經(jīng)...
    沈念sama閱讀 45,782評(píng)論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,957評(píng)論 3 337
  • 正文 我和宋清朗相戀三年诲锹,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了繁仁。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,102評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡归园,死狀恐怖黄虱,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情庸诱,我是刑警寧澤捻浦,帶...
    沈念sama閱讀 35,790評(píng)論 5 346
  • 正文 年R本政府宣布晤揣,位于F島的核電站,受9級(jí)特大地震影響朱灿,放射性物質(zhì)發(fā)生泄漏昧识。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,442評(píng)論 3 331
  • 文/蒙蒙 一母剥、第九天 我趴在偏房一處隱蔽的房頂上張望滞诺。 院中可真熱鬧形导,春花似錦环疼、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至阎曹,卻和暖如春伪阶,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背处嫌。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工栅贴, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人熏迹。 一個(gè)月前我還...
    沈念sama閱讀 48,332評(píng)論 3 373
  • 正文 我出身青樓檐薯,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親注暗。 傳聞我的和親對(duì)象是個(gè)殘疾皇子坛缕,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,044評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容