日韩性视频-久久久蜜桃-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ò),歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 男女免费视频网站 | 欧美伊人 | 久久爱资源网 | 肉丝肉足丝袜一区二区三区 | 久久久91视频 | 激情小说亚洲图片 | 国产色综合天天综合网 | 色伊人网 | 裸体一区二区三区 | 老熟女高潮一区二区三区 | 四虎成人精品在永久免费 | 亚洲jizzjizz日本少妇 | 爱情岛论坛亚洲入口 | 丰满多毛的大隂户视频 | 日韩欧美一区二区三区在线 | 国产三级aaa| 亚洲精品成人影视 | 国产一区黄色 | 99ri国产 | 日本一本一道 | 91黄色在线视频 | 91色国产 | 亚洲国产毛片aaaaa无费看 | 99久久久国产 | 国产精品成人一区二区 | 国产91在线播放精品91 | 3d动漫精品啪啪一区二区竹菊 | 久久免费福利视频 | 国产一区二区三区自拍 | 久久精品亚洲a | 国产成人三级在线观看视频 | 日韩亚洲欧美综合 | 性高跟鞋xxxxhd人妖 | 久久精品片 | 激情片网站 | 亚洲大乳 | 精品不卡视频 | 黄色1级大片 | 成年网站在线 | 在线观看www| 嫩草在线视频 | 精品欧美黑人一区二区三区 | 亚洲一区二区观看播放 | 成人无码www在线看免费 | 六月婷婷在线观看 | 欧美性生交大片免费看 | 久射网| 欧洲成人免费视频 | 免费黄色网址大全 | 国产高清视频网站 | 怡红院av亚洲一区二区三区h | 亚洲一区二区三区免费在线观看 | 亚洲av最新在线网址 | 在线97视频 | 成人a v视频| 免费成人福利视频 | 天天添天天操 | 欧美一二三四五区 | 成人黄色片视频 | 青娱乐国产在线 | 三级中文字幕 | 高潮无码精品色欲av午夜福利 | 中文字幕在线免费观看 | 婷婷五月综合久久中文字幕 | 国产精品久久av | 秘密基地电影免费版观看国语 | wwwav在线播放 | 在线亚洲成人 | 中文字幕一区二区三区四区免费看 | www,超碰| www.欧美色 | 色无五月 | 四虎最新域名 | 神马久久网站 | 国产精品一二三 | 久久精品国产熟女亚洲AV麻豆 | 欧美一区二区不卡视频 | 日本少妇吞精囗交 | 久久精品久久国产 | 国产免费一区二区三区在线观看 | 精品人妻中文无码av在线 | 91在线免费观看网站 | 中文字幕丝袜诱惑 | 久久久久久久久久久久久久国产 | 男人天堂国产 | 最新亚洲精品 | 99久久99久久 | 国产精品免费久久久 | 国产真实夫妇交换视频 | 色婷婷狠狠18禁久久 | 国产精品日日做人人爱 | 影音先锋成人网 | 日韩精品人妻中文字幕 | 奴性白洁会所调教 | 日韩精品人妻一区二区三区免费 | 色啪网站| 久久久久久国产精品三区 | 欧美丰满美乳xxx高潮www | 精品国产1区2区 |