一慨削、ThreadFactoryBuilder
ThreadFactoryBuilder主要用于線程池技術(shù)中兼都。當我們需要給新創(chuàng)建的線程取名字嫂沉、或者設(shè)置為守護線程、錯誤處理器等操作時,線程工廠的好處就提現(xiàn)出來了扮碧。
- 不用ThreadFactoryBuilder的時候 我們這么寫代碼趟章。我們每次要新建一個類來實現(xiàn)ThreadFactory,有點繁瑣。
- 用了ThreadFactoryBuilder之后慎王,好處不言而喻蚓土。ThreadFactoryBuilder是一個Builder設(shè)計模式的應(yīng)用,可以設(shè)置守護進程、錯誤處理器赖淤、線程名字蜀漆。
二、SettableFuture
settableFuture我們可以認為是一種異步轉(zhuǎn)同步的工具咱旱。我們平常只聽說過同步轉(zhuǎn)異步,這次竟然是異步轉(zhuǎn)同步,是不是覺得有點奇怪确丢。先看一下實例:
我們先使用create()創(chuàng)建一個SettableFuture的實例,然后等線程獲取結(jié)果后手動將返回值放入到settableFuture中,類似于一個ThreadLocal.,一切看起來都很自然。但是作用在哪莽龟?個人認為就是get()方法,我們可以設(shè)置超時獲取的時間,如果在指定時間內(nèi)獲取不到,則拋出異常蠕嫁。
應(yīng)用場景:
我們在做網(wǎng)絡(luò)通信時,假設(shè)一般請求-響應(yīng)都是在3秒以內(nèi)拿到結(jié)果.但有的時候遇到網(wǎng)絡(luò)動蕩、硬件性能問題時會導(dǎo)致超時,5秒,10秒甚至更多毯盈。但是我們希望超過5秒的請求我們就認為失敗,這個時候SettableFuture就可以出場了,代碼優(yōu)雅,又能解決實際問題剃毒。
remoteFuture.get(5,TimeUnit.SECONDS);
三、ListenableFuture
ListenableFuture是基于裝飾器模式實現(xiàn)的:
ListeningExecutorService listeningExecutor = MoreExecutors.listeningDecorator(executor);
final ListenableFuture<String> future = listeningExecutor.submit(new Callable<String>() {
@Override
public String call() throws Exception {
TimeUnit.SECONDS.sleep(2);
return "hello_world";
}
});
我們可以對ExecutorService做一層包裝,返回一個ListenableFuture實例,而ListenableFuture又是集成自Future,擴展了一個addListener監(jiān)聽方法,當任務(wù)執(zhí)行完成,會主動回調(diào)該方法。主要也是彌補了JDK自帶Future的不足,像Netty也優(yōu)雅的實現(xiàn)了異步回調(diào)機制,不需要手動通過Future.get()來獲取結(jié)果赘阀。
future.addListener(new Runnable() {
@Override
public void run() {
try {
System.out.println("收到通知..." + future.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}, listeningExecutor);
四益缠、Futures.addCallback
也是基于異步回調(diào)的機制,個人覺得更加雅觀。
Futures.addCallback(future, new FutureCallback<String>() {
@Override
public void onSuccess(String result) {
}
@Override
public void onFailure(Throwable t) {
System.out.println("futureException: ");
t.printStackTrace();
}
});
五基公、AsyncFunction
我們調(diào)用ListenableFuture.get方法取回AsyncFunction接口處理后的結(jié)果幅慌。當我們想要異步地執(zhí)行轉(zhuǎn)換邏輯,而不是阻塞的調(diào)用(雖然任務(wù)還沒有完成的時候調(diào)用Future.get方法會阻塞)的時候轰豆,可以使用AsyncFunction接口胰伍。但是AsyncFunction接口并不會異步的執(zhí)行轉(zhuǎn)換邏輯;而只是返回一個Future實例酸休。 看看下面代碼例子:
public class AsyncFuntionSample implements AsyncFunction<Long,String> {
private ConcurrentMap<Long,String> map = Maps.newConcurrentMap();
private ListeningExecutorService listeningExecutorService;
@Override
public ListenableFuture<String> apply(final Long input) throws Exception {
if(map.containsKey(input)) {
SettableFuture<String> listenableFuture = SettableFuture.create();
listenableFuture.set(map.get(input));
return listenableFuture;
}else{
return listeningExecutorService.submit(new Callable<String>(){
@Override
public String call() throws Exception {
String retrieved = service.get(input);
map.putIfAbsent (input,retrieved);
return retrieved;
}
});
}
}
我們這個類實現(xiàn)AsyncFunction接口骂租,并且包含一個ConcurrentHashMap實例。當我們調(diào)用apply方法時斑司,我們會首先查看下map中有沒有這個值渗饮,輸入對象作為key。如果我們在map中找到值宿刮,我們使用SettableFuture類構(gòu)造出Future對象互站,并且設(shè)置為從map中取出的對象。否則僵缺,我們返回提交Callable給ExecutorService放回的Future對象胡桃。同樣也會放置返回的值到map中去。
六谤饭、補充一下
Futures中還有幾個immediate開頭的方法:
//immediateFuture 表示該方法立即返回
ListenableFuture<String> future = Futures.immediateFuture("immediateFuture");
//實現(xiàn)和immediateFuture差不多,提供了兩個checkedGet()方法
future = Futures.immediateCheckedFuture("immediateCheckedFuture");
//構(gòu)造一個cancel的future,當調(diào)用get()方法時 立即拋出異常
future = Futures.immediateCancelledFuture();
//調(diào)用get()方法和checkedGet()拋出異常
future =Futures.immediateFailedCheckedFuture(newNullPointerException("immediateFailedCheckedFuture"));
//當調(diào)用get()方法時,拋出異常
future = Futures.immediateFailedFuture(new NullPointerException("immediateFailedFuture"));
這些方法一般結(jié)合著Futures的transform使用:
ListeningExecutorService executor = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10));
ListenableFuture<Integer> futures = executor.submit(new Callable<Integer>() {
public Integer call() throws Exception {
Thread.sleep(2000);
System.out.println("future task done......");
return 1;
}
});
//因為futures.get()返回的是Integer,如果想在get()方法返回之后,利用其返回值做一些其他操作.就可以使用
transform()方法,手動轉(zhuǎn)換為對其類型結(jié)果的獲取:
ListenableFuture<Boolean> transform = Futures.transformAsync(futures, new AsyncFunction<Integer, Boolean>() {
public ListenableFuture<Boolean> apply(Integer integer) throws Exception {
return integer > 0 ? Futures.immediateFuture(Boolean.TRUE) : Futures.immediateFuture(Boolean.FALSE);
}
});
使用JdkFutureAdapters來完成JDK Future到ListenableFuture的轉(zhuǎn)換:
ListenableFuture<Boolean> listenFuture = JdkFutureAdapters.listenInPoolThread(transformFuture);
更多詳情可以參考: https://stonelion.gitbooks.io/guava_ch/content/index.html