Java多線程教程之如何利用Future實(shí)現(xiàn)攜帶結(jié)果的任務(wù)
Future 介紹
Future表示異步計(jì)算的結(jié)果,它提供了檢查計(jì)算是否完成的方法,以等待計(jì)算的完成,并檢索計(jì)算的結(jié)果。Future的cancel方法可以取消任務(wù)的執(zhí)行,它有一布爾參數(shù),參數(shù)為 true 表示立即中斷任務(wù)的執(zhí)行,參數(shù)為 false 表示允許正在運(yùn)行的任務(wù)運(yùn)行完成。Future的 get 方法等待計(jì)算完成,獲取計(jì)算結(jié)果。
Runnable
Runnable 是我們多線程開發(fā)過程中常用的接口。 Executor 框架使用 Runnable 作為其基本的任務(wù)表現(xiàn)形式。 Runnable 是一個(gè)有很大局限性的接口,run() 方法沒有返回值并且不能拋出一個(gè)受檢查的異常。
@FunctionalInterface
public interface Runnable {
public abstract void run();
}
Callable
與 Runnable 不同,Callable 是個(gè)泛型參數(shù)化接口,它能返回線程的執(zhí)行結(jié)果,出錯(cuò)時(shí)可能拋出異常。
多線程future
Future
Executor 執(zhí)行的任務(wù)有 4 個(gè)生命周期階段:創(chuàng)建、提交、開始和完成。由于有些任務(wù)執(zhí)行很耗時(shí)間,因此有些時(shí)候希望能夠取消這些任務(wù)。Executor 框架中,已經(jīng)提交但未開始的任務(wù)可以取消,已經(jīng)開始的任務(wù)只有當(dāng)它們能響應(yīng)中斷才能取消,取消已經(jīng)完成的任務(wù)是沒有任何影響。
Future 表示一個(gè)任務(wù)的生命周期,并提供了相應(yīng)的方法來判斷任務(wù)是否已經(jīng)完成或者取消,以及獲取任務(wù)的結(jié)果和取消任務(wù)。
public interface Future<V> {
// 取消任務(wù)
boolean cancel(boolean mayInterruptIfRunning);
// 判斷是否已經(jīng)取消
boolean isCancelled();
// 如果任務(wù)已經(jīng)結(jié)束返回 true
boolean isDone();
// 若有必要會(huì)一直阻塞直到結(jié)束并返回結(jié)果
V get() throws InterruptedException, ExecutionException;
// 若有必要會(huì)阻塞指定的時(shí)間等待結(jié)束并返回結(jié)果
V get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException;
}
ExecutorService 中所有的 submit 方法都返回一個(gè) Future 對(duì)象,從而將一個(gè) Runnable 或 Callable 提交給 Executor, 可以通過返回的 Future 來取消任務(wù)或者獲取返回結(jié)果。
還可以顯示地將某個(gè)指定的 Runnable 或 Callable 實(shí)例化為 FutureTask ,由于 FutureTask 類實(shí)現(xiàn)了 Runnable、Future 接口,因此可以將它提交給 Executor 來執(zhí)行。
FutureTask 繼承關(guān)系:
public class FutureTask<V> implements RunnableFuture<V> {
......
}
public interface RunnableFuture<V> extends Runnable, Future<V> {
void run();
}
Future 和 FutureTask 的一個(gè)區(qū)別在于,F(xiàn)uture 需要通過 ExecutorService 中的 submit 方法的返回值來獲取結(jié)果,而 FutureTask 提交任務(wù)時(shí)不需要設(shè)置返回值,通過自身就可以獲取結(jié)果。
下面來看一個(gè)計(jì)算 0~10 之間的整數(shù)之和并返回結(jié)果的例子:
import java.time.LocalDateTime;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
/**
* @author :jhys
* @date :Created in 2021/7/6 14:43
* @Description :
*/
public class FutureTest1 {
public static void main(String[] args) throws Exception {
ExecutorService executor = Executors.newSingleThreadExecutor();
System.out.println(LocalDateTime.now() + ": thread start");
Future<Integer> future = executor.submit(() -> {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(LocalDateTime.now() + ": task start");
int sum = 0;
for (int i = 0; i <= 10; i++) {
sum += i;
}
return sum;
});
executor.shutdown();
try {
Integer ret = future.get();
System.out.println(LocalDateTime.now() + ": ret = " + ret);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("finish");
}
}
輸出結(jié)果:
2021-07-06T14:49:21.244: thread start
2021-07-06T14:49:24.259: task start
2021-07-06T14:49:24.259: ret = 55
finish
將上面的例子中 Future 替換為 FutureTask ,代碼如下:
public class FutureTest {
public static void main(String[] args) {
FutureTask<Integer> future = new FutureTask<>(() -> {
Thread.sleep(3000);
System.out.println(LocalDateTime.now() + ": task start");
int sum = 0;
for (int i =0; i <= 10; i++) {
sum += i;
}
return sum;
});
ExecutorService executor = Executors.newSingleThreadExecutor();
// 注意這里的區(qū)別,不需要顯示獲取返回值
executor.submit(future);
executor.shutdown();
try {
System.out.println(LocalDateTime.now() + ": ret = " + future.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
System.out.println("finish");
}
}
總結(jié)
到此這篇關(guān)于Java多線程教程之如何利用Future實(shí)現(xiàn)攜帶結(jié)果任務(wù)的文章就介紹到這了,更多相關(guān)Java多線程Future實(shí)現(xiàn)帶結(jié)果任務(wù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家
相關(guān)文章
SpringBoot集成tomcat詳解實(shí)現(xiàn)過程
采用spring boot之后,一切變得如此簡單,打包->java-jar->運(yùn)維,只需要一個(gè)jar包便可以隨意部署安裝。這篇文章,將對(duì) spring boot集成tomcat的源碼進(jìn)行分析,探索其內(nèi)部的原理2023-02-02
在java中由類名和方法名字符串實(shí)現(xiàn)其調(diào)用方式
這篇文章主要介紹了在java中由類名和方法名字符串實(shí)現(xiàn)其調(diào)用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-09-09
基于Calendar獲取當(dāng)前時(shí)間的性能比較
這篇文章主要介紹了Calendar獲取當(dāng)前時(shí)間的性能比較,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06
解決springboot項(xiàng)目啟動(dòng)失敗Could not initialize class&
這篇文章主要介紹了解決springboot項(xiàng)目啟動(dòng)失敗Could not initialize class com.fasterxml.jackson.databind.ObjectMapper問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-06-06
springboot實(shí)現(xiàn)攔截器的3種方式及異步執(zhí)行的思考
實(shí)際項(xiàng)目中,我們經(jīng)常需要輸出請(qǐng)求參數(shù),響應(yīng)結(jié)果,方法耗時(shí),統(tǒng)一的權(quán)限校驗(yàn)等。本文首先為大家介紹 HTTP 請(qǐng)求中三種常見的攔截實(shí)現(xiàn),并且比較一下其中的差異。感興趣的可以了解一下2021-07-07
mybatis動(dòng)態(tài)sql之Map參數(shù)的講解
今天小編就為大家分享一篇關(guān)于mybatis動(dòng)態(tài)sql之Map參數(shù)的講解,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧2019-03-03
Java實(shí)現(xiàn)md5和base64加密解密的示例代碼
這篇文章主要介紹了Java實(shí)現(xiàn)md5和base64加密解密的示例代碼,幫助大家更好的利用Java加密解密文件,感興趣的朋友可以了解下2020-09-09
Java C++ leetcode執(zhí)行一次字符串交換能否使兩個(gè)字符串相等
這篇文章主要為大家介紹了Java C++ leetcode1790執(zhí)行一次字符串交換能否使兩個(gè)字符串相等,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-10-10

