Java并發(fā)編程:Callable弟跑、Future和FutureTask

轉(zhuǎn)載:http://www.cnblogs.com/dolphin0520/p/3949310.html

一.Callable與Runnable

  先說(shuō)一下java.lang.Runnable吧秘血,它是一個(gè)接口胆建,在它里面只聲明了一個(gè)run()方法:

public?interface?Runnable {

????public?abstract?void?run();

}

?  由于run()方法返回值為void類(lèi)型驳庭,所以在執(zhí)行完任務(wù)之后無(wú)法返回任何結(jié)果晴音。

  Callable位于java.util.concurrent包下柔纵,它也是一個(gè)接口,在它里面也只聲明了一個(gè)方法锤躁,只不過(guò)這個(gè)方法叫做call():

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;

}

?  可以看到搁料,這是一個(gè)泛型接口,call()函數(shù)返回的類(lèi)型就是傳遞進(jìn)來(lái)的V類(lèi)型系羞。

  那么怎么使用Callable呢郭计?一般情況下是配合ExecutorService來(lái)使用的,在ExecutorService接口中聲明了若干個(gè)submit方法的重載版本:

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

<T> Future<T> submit(Runnable task, T result);

Future<?> submit(Runnable task);

  第一個(gè)submit方法里面的參數(shù)類(lèi)型就是Callable椒振。

  暫時(shí)只需要知道Callable一般是和ExecutorService配合來(lái)使用的昭伸,具體的使用方法講在后面講述。

  一般情況下我們使用第一個(gè)submit方法和第三個(gè)submit方法澎迎,第二個(gè)submit方法很少使用勋乾。

二.Future

  Future就是對(duì)于具體的Runnable或者Callable任務(wù)的執(zhí)行結(jié)果進(jìn)行取消宋下、查詢(xún)是否完成、獲取結(jié)果辑莫。必要時(shí)可以通過(guò)get方法獲取執(zhí)行結(jié)果学歧,該方法會(huì)阻塞直到任務(wù)返回結(jié)果。

  Future類(lèi)位于java.util.concurrent包下各吨,它是一個(gè)接口:

public?interface?Future<V> {

????boolean?cancel(boolean?mayInterruptIfRunning);

????boolean?isCancelled();

????boolean?isDone();

????V get()?throws?InterruptedException, ExecutionException;

????V get(long?timeout, TimeUnit unit)

????????throws?InterruptedException, ExecutionException, TimeoutException;

}

?  在Future接口中聲明了5個(gè)方法枝笨,下面依次解釋每個(gè)方法的作用:

cancel方法用來(lái)取消任務(wù),如果取消任務(wù)成功則返回true揭蜒,如果取消任務(wù)失敗則返回false横浑。參數(shù)mayInterruptIfRunning表示是否允許取消正在執(zhí)行卻沒(méi)有執(zhí)行完畢的任務(wù),如果設(shè)置true屉更,則表示可以取消正在執(zhí)行過(guò)程中的任務(wù)徙融。如果任務(wù)已經(jīng)完成,則無(wú)論mayInterruptIfRunning為true還是false瑰谜,此方法肯定返回false欺冀,即如果取消已經(jīng)完成的任務(wù)會(huì)返回false;如果任務(wù)正在執(zhí)行萨脑,若mayInterruptIfRunning設(shè)置為true隐轩,則返回true,若mayInterruptIfRunning設(shè)置為false渤早,則返回false职车;如果任務(wù)還沒(méi)有執(zhí)行,則無(wú)論mayInterruptIfRunning為true還是false鹊杖,肯定返回true悴灵。

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

isDone方法表示任務(wù)是否已經(jīng)完成,若任務(wù)完成涯竟,則返回true;

get()方法用來(lái)獲取執(zhí)行結(jié)果空厌,這個(gè)方法會(huì)產(chǎn)生阻塞庐船,會(huì)一直等到任務(wù)執(zhí)行完畢才返回;

get(long timeout, TimeUnit unit)用來(lái)獲取執(zhí)行結(jié)果嘲更,如果在指定時(shí)間內(nèi)筐钟,還沒(méi)獲取到結(jié)果,就直接返回null赋朦。

  也就是說(shuō)Future提供了三種功能:

  1)判斷任務(wù)是否完成篓冲;

  2)能夠中斷任務(wù)李破;

  3)能夠獲取任務(wù)執(zhí)行結(jié)果。

  因?yàn)镕uture只是一個(gè)接口壹将,所以是無(wú)法直接用來(lái)創(chuàng)建對(duì)象使用的嗤攻,因此就有了下面的FutureTask。

三.FutureTask

  我們先來(lái)看一下FutureTask的實(shí)現(xiàn):

1public?class?FutureTask?implements?RunnableFuture<V>

?  FutureTask類(lèi)實(shí)現(xiàn)了RunnableFuture接口诽俯,我們看一下RunnableFuture接口的實(shí)現(xiàn):

public?interface?RunnableFuture?extends?Runnable, Future<V> {

????void?run();

}

?  可以看出RunnableFuture繼承了Runnable接口和Future接口妇菱,而FutureTask實(shí)現(xiàn)了RunnableFuture接口。所以它既可以作為Runnable被線(xiàn)程執(zhí)行暴区,又可以作為Future得到Callable的返回值闯团。

  FutureTask提供了2個(gè)構(gòu)造器:

public?FutureTask(Callable<V> callable) {

}

public?FutureTask(Runnable runnable, V result) {

}

  事實(shí)上,F(xiàn)utureTask是Future接口的一個(gè)唯一實(shí)現(xiàn)類(lèi)仙粱。

四.使用示例

  1.使用Callable+Future獲取執(zhí)行結(jié)果

public?class?Test {

????public?static?void?main(String[] args) {

????????ExecutorService executor = Executors.newCachedThreadPool();

????????Task task =?new?Task();

????????Future<Integer> result = executor.submit(task);

????????executor.shutdown();


????????try?{

????????????Thread.sleep(1000);

????????}?catch?(InterruptedException e1) {

????????????e1.printStackTrace();

????????}


????????System.out.println("主線(xiàn)程在執(zhí)行任務(wù)");


????????try?{

????????????System.out.println("task運(yùn)行結(jié)果"+result.get());

????????}?catch?(InterruptedException e) {

????????????e.printStackTrace();

????????}?catch?(ExecutionException e) {

????????????e.printStackTrace();

????????}


????????System.out.println("所有任務(wù)執(zhí)行完畢");

????}

}

class?Task?implements?Callable<Integer>{

????@Override

????public?Integer call()?throws?Exception {

????????System.out.println("子線(xiàn)程在進(jìn)行計(jì)算");

????????Thread.sleep(3000);

????????int?sum =?0;

????????for(int?i=0;i<100;i++)

????????????sum += i;

????????return?sum;

????}

}

?  執(zhí)行結(jié)果:

子線(xiàn)程在進(jìn)行計(jì)算

主線(xiàn)程在執(zhí)行任務(wù)

task運(yùn)行結(jié)果4950

所有任務(wù)執(zhí)行完畢

  2.使用Callable+FutureTask獲取執(zhí)行結(jié)果

public?class?Test {

????public?static?void?main(String[] args) {

????????//第一種方式

????????ExecutorService executor = Executors.newCachedThreadPool();

????????Task task =?new?Task();

????????FutureTask futureTask =?new?FutureTask<Integer>(task);

????????executor.submit(futureTask);

????????executor.shutdown();


????????//第二種方式房交,注意這種方式和第一種方式效果是類(lèi)似的,只不過(guò)一個(gè)使用的是ExecutorService伐割,一個(gè)使用的是Thread

????????/*Task task = new Task();

????????FutureTask<Integer> futureTask = new FutureTask<Integer>(task);

????????Thread thread = new Thread(futureTask);

????????thread.start();*/


????????try?{

????????????Thread.sleep(1000);

????????}?catch?(InterruptedException e1) {

????????????e1.printStackTrace();

????????}


????????System.out.println("主線(xiàn)程在執(zhí)行任務(wù)");


????????try?{

????????????System.out.println("task運(yùn)行結(jié)果"+futureTask.get());

????????}?catch?(InterruptedException e) {

????????????e.printStackTrace();

????????}?catch?(ExecutionException e) {

????????????e.printStackTrace();

????????}


????????System.out.println("所有任務(wù)執(zhí)行完畢");

????}

}

class?Task?implements?Callable<Integer>{

????@Override

????public?Integer call()?throws?Exception {

????????System.out.println("子線(xiàn)程在進(jìn)行計(jì)算");

????????Thread.sleep(3000);

????????int?sum =?0;

????????for(int?i=0;i<100;i++)

????????????sum += i;

????????return?sum;

????}

}

?  如果為了可取消性而使用 Future 但又不提供可用的結(jié)果候味,則可以聲明 Future<?> 形式類(lèi)型、并返回 null 作為底層任務(wù)的結(jié)果口猜。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末负溪,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子济炎,更是在濱河造成了極大的恐慌川抡,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,378評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件须尚,死亡現(xiàn)場(chǎng)離奇詭異崖堤,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)耐床,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)密幔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人撩轰,你說(shuō)我怎么就攤上這事胯甩。” “怎么了堪嫂?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,702評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵偎箫,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我皆串,道長(zhǎng)淹办,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,259評(píng)論 1 279
  • 正文 為了忘掉前任恶复,我火速辦了婚禮怜森,結(jié)果婚禮上速挑,老公的妹妹穿的比我還像新娘。我一直安慰自己副硅,他們只是感情好姥宝,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,263評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著想许,像睡著了一般伶授。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上流纹,一...
    開(kāi)封第一講書(shū)人閱讀 49,036評(píng)論 1 285
  • 那天糜烹,我揣著相機(jī)與錄音,去河邊找鬼漱凝。 笑死疮蹦,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的茸炒。 我是一名探鬼主播愕乎,決...
    沈念sama閱讀 38,349評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼壁公!你這毒婦竟也來(lái)了奈应?” 一聲冷哼從身側(cè)響起竿音,我...
    開(kāi)封第一講書(shū)人閱讀 36,979評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后乔妈,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體彼水,經(jīng)...
    沈念sama閱讀 43,469評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡凭语,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,938評(píng)論 2 323
  • 正文 我和宋清朗相戀三年蛾绎,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片撞反。...
    茶點(diǎn)故事閱讀 38,059評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡妥色,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出遏片,到底是詐尸還是另有隱情嘹害,我是刑警寧澤,帶...
    沈念sama閱讀 33,703評(píng)論 4 323
  • 正文 年R本政府宣布吮便,位于F島的核電站笔呀,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏线衫。R本人自食惡果不足惜凿可,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,257評(píng)論 3 307
  • 文/蒙蒙 一惑折、第九天 我趴在偏房一處隱蔽的房頂上張望授账。 院中可真熱鬧枯跑,春花似錦、人聲如沸白热。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,262評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)屋确。三九已至纳击,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間攻臀,已是汗流浹背焕数。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留刨啸,地道東北人堡赔。 一個(gè)月前我還...
    沈念sama閱讀 45,501評(píng)論 2 354
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像设联,于是被迫代替她去往敵國(guó)和親善已。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,792評(píng)論 2 345

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