摘要:本人郵箱歡迎轉(zhuǎn)載轉(zhuǎn)載請(qǐng)注明網(wǎng)址代碼已經(jīng)全部托管有需要的同學(xué)自行下載引言前面我們講了那么多有關(guān)線程的知識(shí)不知道讀者有沒(méi)有想過(guò)這么一個(gè)問(wèn)題如果有這么一個(gè)比較耗時(shí)的任務(wù)必須使用線程來(lái)執(zhí)行但是在這個(gè)任務(wù)執(zhí)行完之后我需要得到這個(gè)線程的返回值以目前我們
引言本人郵箱:
歡迎轉(zhuǎn)載,轉(zhuǎn)載請(qǐng)注明網(wǎng)址 http://blog.csdn.net/tianshi_kco
github: https://github.com/kco1989/kco
代碼已經(jīng)全部托管github有需要的同學(xué)自行下載
前面我們講了那么多有關(guān)線程的知識(shí).不知道讀者有沒(méi)有想過(guò)這么一個(gè)問(wèn)題,如果有這么一個(gè)比較耗時(shí)的任務(wù),必須使用線程來(lái)執(zhí)行,但是在這個(gè)任務(wù)執(zhí)行完之后,我需要得到這個(gè)線程的返回值.以目前我們學(xué)到的知識(shí),具體實(shí)現(xiàn),我這里不說(shuō),大家自行發(fā)揮.除此之外,如果線程發(fā)生了非運(yùn)行時(shí)異常,我們?cè)谥骶€程就會(huì)收到一堆錯(cuò)誤信息.還有我們也無(wú)法判斷任務(wù)是否執(zhí)行完成,有些人會(huì)說(shuō)用Thread1.isAlive()就可以判斷任務(wù)是否執(zhí)行完成.這是錯(cuò)的,因?yàn)?b>isAlive只是判斷線程是否存活,而無(wú)法判斷任務(wù)是否完成,兩者是不一樣的概念.如果有沒(méi)有不明白的,請(qǐng)考慮使用線程池ThreadPoolExecutor的情況.
以上說(shuō)了那么多,其實(shí)就是為了引入今天要講的Callable,Future,FutureTask.ok,讓我們看一下這些類是干什么的.
*Callable 可以說(shuō)是 Runnable的升級(jí)版本,既有拋出錯(cuò)誤也有返回類型.
*Future 是執(zhí)行異步任務(wù)后的返回值,這個(gè)接口包括一下幾個(gè)方法
* `cancel(boolean mayInterruptIfRunning)` 取消任務(wù),如果`mayInterruptIfRunning`為`true`,即使該任務(wù)在運(yùn)行也可以被中斷.否則在運(yùn)行中的任務(wù)不能被取消. * `isCancelled`判斷任務(wù)是否被取消 * `isDone` 判斷任務(wù)是否完成 * `get` 獲取任務(wù)的返回值,如果任務(wù)有異常,則在調(diào)用這個(gè)方法的時(shí)候被拋出 * `get(long timeout, TimeUnit unit)` 在指定時(shí)間內(nèi)等待獲取任務(wù)的返回值,如果任務(wù)有異常,則在調(diào)用這個(gè)方法的時(shí)候被拋出
FutureTask 是Runnable和Future的子類
例子1 獲取異步任務(wù)的返回值 Runnable 版本public class Demo1 { public static void main(String[] args) throws ExecutionException, InterruptedException { System.out.println("main start"); FutureTask task = new FutureTask(() -> System.out.println("執(zhí)行子任務(wù)"), "hello"); new Thread(task).start(); while (task.isDone()); System.out.println("任務(wù)返回結(jié)果:" + task.get()); System.out.println("main end"); } }
運(yùn)行結(jié)果
main start
執(zhí)行子任務(wù)
任務(wù)返回結(jié)果:hello
main end
public FutureTask(Runnable runnable, V result) 這個(gè)比較適合固定任務(wù)返回固定值的情況,如果返回的值需要進(jìn)過(guò)計(jì)算,所以有多個(gè)情況,則不適合使用這個(gè)構(gòu)造.
例子1 獲取異步任務(wù)的返回值 Callable 版本public class Demo2 { public static void main(String[] args) throws ExecutionException, InterruptedException { System.out.println("main start"); FutureTask task = new FutureTask(() -> { int sum = 0; for (int i = 1; i <= 100; i++){ sum += i; } return sum; }); new Thread(task).start(); while (task.isDone()); System.out.println("任務(wù)返回結(jié)果:" + task.get()); System.out.println("main end"); } }
返回結(jié)果
例子3 測(cè)試運(yùn)行時(shí)異常情況main start
任務(wù)返回結(jié)果:5050
main end
public class Demo3 { public static void main(String[] args) throws ExecutionException, InterruptedException { System.out.println("main start"); FutureTask task = new FutureTask(() -> { System.out.println("正在執(zhí)行子任務(wù)"); int i = 1 / 0; return 0; }); new Thread(task).start(); while (task.isDone()); System.out.println("任務(wù)返回結(jié)果:" + task.get()); System.out.println("main end"); } }
運(yùn)行結(jié)果:
main start
正在執(zhí)行子任務(wù)
Exception in thread "main" java.util.concurrent.ExecutionException: java.lang.ArithmeticException: / by zero
at java.util.concurrent.FutureTask.report(FutureTask.java:122)
at java.util.concurrent.FutureTask.get(FutureTask.java:192)
at com.kco.test18.demo.Demo3.main(Demo3.java:19)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
Caused by: java.lang.ArithmeticException: / by zero
at com.kco.test18.demo.Demo3.lambda$main$0(Demo3.java:14)
at com.kco.test18.demo.Demo3$$Lambda$1/27095111.call(Unknown Source)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.lang.Thread.run(Thread.java:745)
需要注意的是,這是拋出的異常是在調(diào)用task.get()才拋出的,如果把task.get()注釋掉,是不會(huì)拋出異常的.所以我們就可以對(duì)異常做一下自定義處理.比如寫(xiě)到日志中.
例子4 取消正在執(zhí)行的任務(wù)public class Demo4 { public static void main(String[] args) throws ExecutionException, InterruptedException { System.out.println("main start"); FutureTask task = new FutureTask(() -> { System.out.println("start 正在執(zhí)行子任務(wù)"); Thread.sleep(500); System.out.println("end 執(zhí)行子任務(wù)"); return 0; }); new Thread(task).start(); Thread.sleep(250); task.cancel(true); System.out.println("main end"); } }
運(yùn)行結(jié)果
main start
start 正在執(zhí)行子任務(wù)
main end
發(fā)現(xiàn)子任務(wù)確實(shí)運(yùn)行運(yùn)行了一般,然后被取消了.
補(bǔ)充上一篇講到了ThreadPoolExecutor,我們?cè)趫?zhí)行任務(wù)的時(shí)候只使用了execute,這個(gè)是沒(méi)有返回值的.而且如果任務(wù)拋出異常,則會(huì)直接在主線程打印出錯(cuò)誤堆棧的.其實(shí)ThreadPoolExecutor還有另外一個(gè)提交任務(wù)的方法,就是submit(Runnable task, T result)和submit(Callable
如果覺(jué)得我的文章寫(xiě)的還過(guò)得去的話,有錢就捧個(gè)錢場(chǎng),沒(méi)錢給我捧個(gè)人場(chǎng)(幫我點(diǎn)贊或推薦一下)
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/69971.html
摘要:本文首發(fā)于一世流云的專欄一模式簡(jiǎn)介模式是多線程設(shè)計(jì)模式中的一種常見(jiàn)模式,它的主要作用就是異步地執(zhí)行任務(wù),并在需要的時(shí)候獲取結(jié)果。二中的模式在多線程基礎(chǔ)之模式中,我們?cè)?jīng)給出過(guò)模式的通用類關(guān)系圖。 showImg(https://segmentfault.com/img/bVbiwcx?w=1000&h=667); 本文首發(fā)于一世流云的專欄:https://segmentfault.co...
摘要:同步包裝器任何集合類使用同步包裝器都會(huì)變成線程安全的,會(huì)將集合的方法使用鎖加以保護(hù),保證線程的安全訪問(wèn)。線程池中的線程執(zhí)行完畢并不會(huì)馬上死亡,而是在池中準(zhǔn)備為下一個(gè)請(qǐng)求提供服務(wù)。 多線程并發(fā)修改一個(gè)數(shù)據(jù)結(jié)構(gòu),很容易破壞這個(gè)數(shù)據(jù)結(jié)構(gòu),如散列表。鎖能夠保護(hù)共享數(shù)據(jù)結(jié)構(gòu),但選擇線程安全的實(shí)現(xiàn)更好更容易,如阻塞隊(duì)列就是線程安全的集合。 線程安全的集合 Vector和HashTable類提供了線...
摘要:線程的啟動(dòng)與銷毀都與本地線程同步。操作系統(tǒng)會(huì)調(diào)度所有線程并將它們分配給可用的。框架的成員主要成員線程池接口接口接口以及工具類。創(chuàng)建單個(gè)線程的接口與其實(shí)現(xiàn)類用于表示異步計(jì)算的結(jié)果。參考書(shū)籍并發(fā)編程的藝術(shù)方騰飛魏鵬程曉明著 在java中,直接使用線程來(lái)異步的執(zhí)行任務(wù),線程的每次創(chuàng)建與銷毀需要一定的計(jì)算機(jī)資源開(kāi)銷。每個(gè)任務(wù)創(chuàng)建一個(gè)線程的話,當(dāng)任務(wù)數(shù)量多的時(shí)候,則對(duì)應(yīng)的創(chuàng)建銷毀開(kāi)銷會(huì)消耗大量...
摘要:在這個(gè)示例中我們使用了一個(gè)單線程線程池的。在延遲消逝后,任務(wù)將會(huì)并發(fā)執(zhí)行。這是并發(fā)系列教程的第一部分。第一部分線程和執(zhí)行器第二部分同步和鎖第三部分原子操作和 Java 8 并發(fā)教程:線程和執(zhí)行器 原文:Java 8 Concurrency Tutorial: Threads and Executors 譯者:BlankKelly 來(lái)源:Java8并發(fā)教程:Threads和Execut...
閱讀 2942·2021-11-24 09:39
閱讀 1197·2021-11-02 14:38
閱讀 4214·2021-09-10 11:26
閱讀 2785·2021-08-25 09:40
閱讀 2341·2019-08-30 15:54
閱讀 507·2019-08-30 10:56
閱讀 2799·2019-08-26 12:14
閱讀 3246·2019-08-26 12:13