日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

Callable和Future、FutureTask的使用

發(fā)布時(shí)間:2025/3/20 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Callable和Future、FutureTask的使用 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

http://www.silencedut.com/2016/06/15/Callable%E5%92%8CFuture%E3%80%81FutureTask%E7%9A%84%E4%BD%BF%E7%94%A8/

并發(fā)的學(xué)習(xí)與使用系列?第四篇

在Java中,開啟一個(gè)線程的唯一方式是,是通過Thread的start方法,并且在線程中執(zhí)行的Runnable的run方法。無論是線程池還是接下來要介紹的Callable,Future還是線程池,最核心最根本的還是調(diào)用到Thread.start()–>Runnable.run(),其他的類的出現(xiàn)可以認(rèn)為是更方便的使用Thread和Runnable,以此為核心會(huì)更容易理解Java的并發(fā)框架。

雖然Thread和Runnable類使得多線程編程簡(jiǎn)單直接,但有一個(gè)缺陷就是:在執(zhí)行完任務(wù)之后無法獲取執(zhí)行結(jié)果。如果需要獲取執(zhí)行結(jié)果,就必須通過共享變量或者使用線程通信的方式來達(dá)到效果,這樣使用起來就比較麻煩。因此從Jdk1.5開始,有了一系列的類的出現(xiàn)來解決這些問題,如Callable和Future,FutureTask以及下篇要講到的線程池從使用到原理學(xué)習(xí)Java線程池。

而自從Java 1.5開始,就提供了Callable和Future以及FutureTask,通過它們可以在任務(wù)執(zhí)行完畢之后得到任務(wù)執(zhí)行結(jié)果。

實(shí)現(xiàn)原理

Thread和Runnable

首先看Thread和Runnable的實(shí)現(xiàn)多線程任務(wù)的原理。

以下是簡(jiǎn)化后的代碼,為了方便理解。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 public class Thread implements Runnable { Runnable target; public Thread(Runnable runnable) { target = Runnable; //省略其他初始化線程的任務(wù) } public void start() { nativeCreate(this, stackSize, daemon);//native方法開啟多線程,并調(diào)用run方法 } public void run() { if (target != null) { target.run(); } } }

可以看出target是一個(gè)Runnble對(duì)象,通過一個(gè)典型的裝飾模式來擴(kuò)展Runnable,如果不傳入,默認(rèn)為null,需要自己實(shí)現(xiàn)run方法來在新線程里執(zhí)行任務(wù),否則線程不會(huì)做任何事情就結(jié)束。所以無論怎么變化,最終都是Thread的start方法開啟新線程,run方法在這個(gè)新開啟的線程里執(zhí)行任務(wù),當(dāng)然run方法也可以單獨(dú)調(diào)用,但所在線程是調(diào)用者的線程。

裝飾者模式的典型特點(diǎn):裝飾后的類和被裝飾的類,類型不變(繼承Runnable),提供新的行為,方法(start()等),關(guān)于設(shè)計(jì)模式的詳細(xì)細(xì)節(jié),見常見的設(shè)計(jì)模式解讀。

Callable和Future,FutureTask

先通過UML圖來看它們和Thrad,Runnable之間的關(guān)系:

Callable與Runnable的功能大致相似,Callable中有一個(gè)call()函數(shù),但是call()函數(shù)有返回值,而Runnable的run()函數(shù)不能將結(jié)果返回給客戶程序。

Future就是對(duì)Callable任務(wù)的執(zhí)行結(jié)果進(jìn)行取消、查詢是否完成、獲取結(jié)果、設(shè)置結(jié)果操作。其中的get()方法就是用來得到Callable的call()結(jié)果的。

FutureTask是Future的具體實(shí)現(xiàn)類,實(shí)現(xiàn)了get()等方法來對(duì)控制Callabel的行為,又因?yàn)門hread只能執(zhí)行Runnable,所以FutureTask實(shí)現(xiàn)了Runnable接口。

因?yàn)镕utureTask需要在Thread中執(zhí)行,所以需要在run()方法中完成具體的實(shí)現(xiàn):

1 2 3 4 5 6 7 8 9 10 //簡(jiǎn)化后的代碼,為了方便理解 public void run() { Callable<V> c = callable; if (c != null && state == NEW) { V result; result = c.call(); set(result); } }

通過get方法來獲取結(jié)果,get()是個(gè)阻塞方法,直到結(jié)果返回,或者中斷發(fā)生。還可以通過get(long timeout, TimeUnit unit)方法控制等待結(jié)果的最大時(shí)間。

1 2 3 4 5 6 public V get() throws InterruptedException, ExecutionException { int s = state; if (s <= COMPLETING) s = awaitDone(false, 0L);//阻塞等待 return report(s); }

可以看出FutureTask的run方法實(shí)際的任務(wù)是在Callable的call中完成,FutureTask的實(shí)現(xiàn)方式采用了適配器模式來完成。

如果構(gòu)造函數(shù)傳入的是Runnable,則通過Executors的靜態(tài)函數(shù)callable(Runnable task,…)將Runnable轉(zhuǎn)換為Callable類型:

1 2 3 4 5 6 public static Callable callable(Runnable task, T result) { if (task == null) throw new NullPointerException(); return new RunnableAdapter(task, result); }

適配器模式的典型特點(diǎn):包裝另一個(gè)對(duì)象(包裝了Callable),提供不同的接口(Runnable接口)

Callable和Future,FutureTask經(jīng)常容易讓人記憶混亂,理解后就知道了其實(shí)Future和FutureTask就是用來將Callable包裝成一個(gè)Runnable,這樣才能夠在Thread中執(zhí)行,同時(shí)提供將結(jié)果返回的功能,三個(gè)類總是同時(shí)出現(xiàn),整體理解為是一個(gè)可以得到返回結(jié)果的Runnable。

使用

那么怎么使用這些類呢呢?由于FutureTask實(shí)現(xiàn)了Runnable,因此它既可以通過Thread包裝來直接執(zhí)行,也可以提交給ExecuteService來執(zhí)行,在Thread中,就像使用Runnable一樣。

關(guān)于線程池的更多細(xì)節(jié)將在下一篇文章中進(jìn)行講解

示例代碼如下:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 /** * Created by SilenceDut on 16/7/15. **/ public class FutureTest { public static void main(String[] args) { FutureTest futureTest = new FutureTest(); futureTest.useExecutor(); futureTest.useThread(); } private void useExecutor() { SumTask sumTask = new SumTask(1000); ExecutorService executor = Executors.newCachedThreadPool(); FutureTask<Integer> futureTask = new FutureTask<Integer>(sumTask); executor.submit(futureTask); executor.shutdown(); try { System.out.println(Thread.currentThread().getName()+"::useExecutor運(yùn)行結(jié)果" + futureTask.get()); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } } private void useThread() { SumTask sumTask = new SumTask(500); FutureTask<Integer> futureTask = new FutureTask<Integer>(sumTask) { @Override protected void done() { super.done(); try { // 這是在后臺(tái)線程 System.out.println(Thread.currentThread().getName()+"::useThread運(yùn)行結(jié)果" + get()); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } } }; Thread thread = new Thread(futureTask); thread.start(); try { //這是在主線程,會(huì)阻塞 System.out.println(Thread.currentThread().getName()+"::useThread運(yùn)行結(jié)果" + futureTask.get().getName()); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } } class SumTask implements Callable<Integer> { int number; public SumTask(int num) { this.number = num; } @Override public Integer call() throws Exception { System.out.println(Thread.currentThread().getName()); Thread.sleep(5000); int sum = 0; for (int i = 0; i < number; i++) { sum += i; } return sum; } } }

結(jié)果:

pool-1-thread-1 main::useExecutor運(yùn)行結(jié)果499500 Thread-0 main::useThread運(yùn)行結(jié)果124750 Thread-0::useThread運(yùn)行結(jié)果124750

FutureTask.get()是阻塞的,useExecutor()和useThread()也會(huì)阻塞。這里只是說明FutureTask.get()所在的線程是調(diào)用者所在的線程,在Android中使用的話,一般是在FutureTask的done方法中g(shù)et,這時(shí)get就是在后臺(tái)線程調(diào)用了,然后通過Handler通知到UI或其他線程。我寫了一個(gè)AysncTask替代庫(kù)AsyncTaskScheduler,實(shí)現(xiàn)了通過線程池調(diào)用和單個(gè)線程調(diào)用的具體方式,里面有具體的實(shí)現(xiàn)方式。

轉(zhuǎn)載于:https://www.cnblogs.com/bigben0123/p/8243720.html

總結(jié)

以上是生活随笔為你收集整理的Callable和Future、FutureTask的使用的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 白嫩初高中害羞小美女 | 欧美老熟妇喷水 | 中韩毛片| 好吊日免费视频 | 1024国产视频 | 日韩中文欧美 | 日韩成人区 | 四季av中文字幕一区 | 色婷婷基地 | av在线不卡一区 | 欧美另类tv | 国产激情av一区二区三区 | 91国偷自产一区二区三区老熟女 | av色在线观看 | 黄色在线资源 | 欧日韩一区二区三区 | 国内激情视频 | 亚洲精品 欧美 | 91尤物视频 | www超碰 | 一起操在线 | 用我的手指扰乱你 | 亚洲AV无码国产精品国产剧情 | 99成人精品 | 成人免费视频网站 | 国产综合视频一区二区 | 国产又好看的毛片 | 在线观看成人动漫 | 午夜av激情 | 色偷偷av一区二区三区 | 丰满放荡岳乱妇91ww | 筱田优av | 特级毛片在线播放 | 久久只有这里有精品 | 女同在线视频 | 日本福利在线 | 成年人激情网站 | 超碰在线日韩 | 午夜三级在线观看 | 午夜视频黄色 | 久久久久久av无码免费网站 | 欧美三级视频 | 少妇一区二区三区四区 | 日韩激情啪啪 | 蜜臀av一区| 午夜天堂网 | www.成人免费视频 | 久久亚洲电影 | juliaann精品艳妇hd | 国产原创91 | 亚洲黄色网络 | 日韩欧美亚洲 | 国产精品成人一区 | 日p免费视频 | 久草视频免费在线观看 | 亚洲性综合网 | 古代玷污糟蹋np高辣h文 | 欧美三级网 | 少妇无套内谢免费视频 | 在线观看国产一区二区三区 | 欧美日韩在线播放 | 欧美成人a | 中文字幕婷婷 | 无码人妻精品一区二区三区温州 | 黄色av网站免费在线观看 | 欧洲性生活视频 | 黄污视频在线播放 | 五月天婷婷久久 | 在线观看免费成人 | 国产九九精品视频 | 三级黄色免费片 | 国产精品久久99 | 久久国内精品 | 啪啪网站免费 | 人妻精油按摩bd高清中文字幕 | 国产成人精品一区二区在线观看 | 日韩黄色一级视频 | 福利小视频在线观看 | 偷看洗澡一二三区美女 | 亚洲精品国产精品国自产网站按摩 | 哪里可以看毛片 | 天天草综合 | 国产欧美在线精品日韩 | 欧美性猛交性大交 | 成人av一区二区三区在线观看 | 草草久久久 | 特级新鲜大片片 | 爱的色放3| 黄色欧美一级片 | 一区二区三区四区精品 | 亚洲大片在线观看 | 奇米第四色在线 | 国产精品一区三区 | 国产精品免费久久久久 | 青青久久av | 亚洲av日韩精品久久久久久久 | 国产3p视频 | 欧美黄色图片 | 亚洲综合图色40p |