久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

Java異步編程接口:Callable和Future | Aoho''s Blog

 airen89 2018-09-18

本文主要講解平時開發(fā)中常用的異步編程的接口:Callable和Future,。

創(chuàng)建線程的2種方式,,一種是直接繼承Thread,,另外一種就是實現(xiàn)Runnable接口。這2種方式都有一個缺陷就是:在執(zhí)行完任務(wù)之后無法獲取執(zhí)行結(jié)果,。如果需要獲取執(zhí)行結(jié)果,,就必須通過共享變量或者使用線程通信的方式來達(dá)到效果,這樣使用起來就比較麻煩,。
自從Java 1.5開始,,就提供了CallableFuture,通過它們可以在任務(wù)執(zhí)行完畢之后得到任務(wù)執(zhí)行結(jié)果,。

Callable

Callable接口的定義如下:

1
2
3
4
public interface Callable<V> {
V call() throws Exception;
}

Callable中定義了 call() 方法計算結(jié)果,,或者當(dāng)不能執(zhí)行的時候拋出異常,可以看到返回值的類型是通過傳入的泛型決定,。

Callable并不像Runnable那樣通過Thread的start方法就能啟動實現(xiàn)類的run方法,,所以它通常利用ExecutorService的submit方法去啟動call方法自執(zhí)行任務(wù),而ExecutorService的submit又返回一個Future類型的結(jié)果,,因此Callable通常也與Future一起使用

1
2
3
4
5
6
ExecutorService pool = Executors.newCachedThreadPool();
Future<String> future = pool.submit(new Callable {
public void call(){
//your operations
}
});

vs Runnable

RunnableCallable不同點:

  1. Runnable不返回任務(wù)執(zhí)行結(jié)果,,Callable可返回任務(wù)執(zhí)行結(jié)果;
  2. Callable在任務(wù)無法計算結(jié)果時拋出異常,,而Runnable不能,;
  3. Callable支持泛型,,Runnable不支持;
  4. Runnable任務(wù)可直接由Thread的start方法或ExecutorService的submit方法去執(zhí)行,。

Future

Future保存異步計算的結(jié)果,可以在我們執(zhí)行任務(wù)時去做其他工作,,并提供了以下幾個方法:

1
2
3
4
5
6
7
8
9
10
11
12
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;
}
  • cancel(boolean mayInterruptIfRunning):試圖取消執(zhí)行的任務(wù),參數(shù)為true時直接中斷正在執(zhí)行的任務(wù),,否則直到當(dāng)前任務(wù)執(zhí)行完成,,成功取消后返回true,否則返回false
  • isCancel():判斷任務(wù)是否在正常執(zhí)行完前被取消的,,如果是則返回true
  • isDone():判斷任務(wù)是否已完成
  • get():等待計算結(jié)果的返回,,如果計算被取消了則拋出
  • get(long timeout,TimeUtil unit):設(shè)定計算結(jié)果的返回時間,如果在規(guī)定時間內(nèi)沒有返回計算結(jié)果則拋出TimeOutException

使用Future的好處:

  • 獲取任務(wù)的結(jié)果,,判斷任務(wù)是否完成,,中斷任務(wù)
  • Future的get方法很好的替代的了Thread.join或Thread,join(long millis)
  • Future的get方法可以判斷程序代碼(任務(wù))的執(zhí)行是否超時

FutureTask

FutureTask實現(xiàn)了RunnableFuture<V>接口,關(guān)于該接口看一下其定義:

1
2
3
4
public interface RunnableFuture<V> extends Runnable, Future<V> {
void run();
}

RunnableFuture同時繼承了RunnableFuture,,接口中定義的run方法,,將計算的結(jié)果設(shè)置到Future除非計算被取消。所以它既可以作為Runnable被線程執(zhí)行,,又可以作為Future得到Callable的返回值,。

FutureTask可以直接提交給Executor執(zhí)行,當(dāng)然也可以調(diào)用線程直接執(zhí)行FutureTask.run(),。

FutureTask是一個可取消的異步計算,,FutureTask 實現(xiàn)了Future的基本方法,提供start和cancel 操作,,可以查詢計算是否已經(jīng)完成,,并且可以獲取計算的結(jié)果。
結(jié)果只可以在計算完成之后獲取,,get方法會阻塞當(dāng)計算沒有完成的時候,,一旦計算已經(jīng)完成, 那么計算就不能再次啟動或是取消,。

使用示例

示例場景:有一個耗時的操作,,操作完后會返回一個結(jié)果(不管是正常結(jié)果還是異常),程序如果想擁有比較好的性能不可能由線程去等待操作的完成,,而是應(yīng)該采用listener模式,。jdk并發(fā)包里的Future代表了未來的某個結(jié)果,當(dāng)我們向線程池中提交任務(wù)的時候會返回該對象,。
提交一個Callable對象給線程池時,,將得到一個Future對象,并且它和傳入的Callable有相同的結(jié)果類型聲明。

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
public class FutureTest {
public static void main(String[] args) throws Throwable, ExecutionException {
ExecutorService executor = Executors.newFixedThreadPool(2);
//Java8 的lambada表達(dá)式,,參數(shù)為Callable<T> task
Future<String> f = executor.submit(() -> {
System.out.println("task started!");
Thread.sleep(1000);
return "worker task finished!";
});
System.out.println("Future is ready: " + f.isDone());
//此處阻塞main線程
System.out.println(f.get());
executor.shutdown();
System.out.println("main thread is finished,!");
}
//FutureTask的寫法
public static void test() throws Throwable, ExecutionException {
FutureTask<String> f = new FutureTask<>(() -> {
System.out.println("task started!");
Thread.sleep(1000);
return "worker task finished!";
});
Thread thread = new Thread(f);
thread.start();
System.out.println("Future is ready: " + f.isDone());
//此處阻塞main線程
System.out.println(f.get());
System.out.println("main thread is finished!");
}
}

運(yùn)行結(jié)果如下:

1
2
3
4
Future is ready: false
task started!
worker task finished!
main thread is finished,!

如果想獲得耗時操作的結(jié)果,,可以通過get方法獲取,但是該方法會阻塞當(dāng)前線程,,我們可以在做完剩下的某些工作的時候調(diào)用get方法試圖去獲取結(jié)果,,也可以調(diào)用非阻塞的方法isDone來確定操作是否完成。過程如下:

Future代表了線程執(zhí)行完以后的結(jié)果,,可以通過future獲得執(zhí)行的結(jié)果,。但是jdk1.8之前的Future不支持,并不能實現(xiàn)真正的異步,,需要阻塞的獲取結(jié)果,,或者不斷的輪詢。通常我們希望當(dāng)線程執(zhí)行完一些耗時的任務(wù)后,,能夠自動的通知我們結(jié)果,,很遺憾這在原生jdk1.8之前
是不支持的,但是我們可以通過第三方的庫實現(xiàn)真正的異步回調(diào),。如Guava何Netty中都有提供,,讀者可以自己進(jìn)行擴(kuò)展,下面我們看一下JDK8中的實現(xiàn),。

Java8 CompletableFuture

雖然Future以及相關(guān)使用方法提供了異步執(zhí)行任務(wù)的能力,,但是對于結(jié)果的獲取卻是很不方便,,只能通過阻塞或者輪詢的方式得到任務(wù)的結(jié)果,。阻塞的方式顯然和我們的異步編程的初衷相違背,輪詢的方式又會耗費(fèi)無謂的CPU資源,,而且也不能及時地得到計算結(jié)果,。
CompletableFuture類實現(xiàn)了CompletionStage和Future接口,所以你還是可以像以前一樣通過阻塞或者輪詢的方式獲得結(jié)果,,盡管這種方式不推薦使用,。這里使用CompletableFuture實現(xià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
public class Java8PromiseTest {
public static void main(String[] args) throws Throwable, ExecutionException {
ExecutorService executor = Executors.newFixedThreadPool(2);
//jdk1.8,通過調(diào)用給定的Supplier,,異步完成executor中的task
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
System.out.println("task started!");
try {
//模擬耗時操作
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "worker task is finished!";
}, executor);
//采用lambada的實現(xiàn)方式
future.thenAccept(e -> {
System.out.printf("%s ok", e);
executor.shutdown();
});
System.out.println("main thread is finished,!");
}
}

運(yùn)行結(jié)果如下:

1
2
3
task started!
main thread is finished!
worker task is finished! ok

supplyAsync方法以Supplier函數(shù)式接口類型為參數(shù),CompletableFuture的計算結(jié)果類型為U,。thenAccept方法是CompletableFuture提供的一種處理結(jié)果的方法,,只對結(jié)果執(zhí)行Action,而不返回新的計算值,因此計算值為Void。

總結(jié)

本文主要介紹了異步編程經(jīng)常使用的Callable,、Future以及FutureTask,。運(yùn)行Callable任務(wù)可以拿到一個Future對象,F(xiàn)uture 表示異步計算的結(jié)果,。它提供了檢查計算是否完成的方法,,以等待計算的完成,并獲取計算的結(jié)果,。計算完成后只能使用 get 方法來獲取結(jié)果,,如果線程沒有執(zhí)行完,F(xiàn)uture.get()方法可能會阻塞當(dāng)前線程的執(zhí)行,;如果線程出現(xiàn)異常,,Future.get()會拋出異常。
取消由cancel 方法來執(zhí)行,。isDone確定任務(wù)是正常完成還是被取消了,。一旦計算完成,就不能再取消計算,。如果為了可取消性而使用 Future 但又不提供可用的結(jié)果,,則可以聲明Future<?> 形式類型、并返回 null 作為底層任務(wù)的結(jié)果,。

參考

  1. java異步編程
  2. Java并發(fā)編程:Callable,、Future和FutureTask

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點,。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報,。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多