Guava 6:Concurrency

1、引子

有點經驗的工程師必定對多線程比較熟悉,JDK封裝的FutureTask實現了這一功能。以下圖:web

FutureTask實現了RunnableFuture接口,而RunnableFuture接口繼承了Future+Runnable共2個接口。所以,FutureTask支持線程執行任務run(),也支持get()等待任務完成、cancel()取消任務等。可是明顯仍是不夠。服務器

Guava的併發包,強大而簡單的抽象,讓編寫正確的併發代碼更簡單多線程

1.ListenableFuture接口

ListenableFuture接口並繼承了JDK concurrent包下的Future 接口。配合Futures工具類,能夠很方便的實現如下功能:併發

1)監放任務執行結果並執行回調方法。app

2)提供方便的任務接口轉換。框架

3)多線程併發執行取結果集合。異步

2.Service框架

抽象可開啓和關閉的服務,幫助你維護服務的狀態邏輯ide

2、簡單應用

2.1 ListenableFuture接口

2.1.1 監放任務執行結果並執行回調方法

實現功能:

1)定義監聽執行器。工具

2)定義可監聽的帶返回值任務。spa

3)定義回調方法。

3)綁定任務、執行器、回調方法。

源碼以下:

 1 public static void main(String[] args) throws ExecutionException, InterruptedException {
 2         /** 1.典型用法:可監聽的future,帶回調方法 */
 3         // 定義監聽執行服務
 4         ListeningExecutorService listeningExecutorService = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10));
 5         // 定義可監聽的帶返回值的任務
 6         ListenableFuture<String> callableListenableFuture1 = listeningExecutorService.submit(() -> {
 7             System.out.println("callable1 call!");
 8             return "1";
 9         });
10         // 添加回調,由指定監聽執行服務來執行,監聽可監聽的future,監聽到事件時執行對應回調方法。
11         Futures.addCallback(callableListenableFuture1, new FutureCallback<String>() {
12             @Override
13             public void onSuccess(@Nullable String result) {
14                 System.out.println("success,result=" + result);
15             }
16 
17             @Override
18             public void onFailure(Throwable t) {
19                 System.out.println("fail!");
20             }
21         }, listeningExecutorService);
22 }

打印結果:

callable1 call!
success,result=1

2.1.2 提供方便的任務接口轉換

實現功能:

1) 定義一個須要綁定的ListenableFuture

2)定義一個異步轉換方法

3)定義一個線程任務執行器

4)調用Futures工具類的transformAsync方法實現轉換

源碼以下:

 1 public static void main(String[] args) throws ExecutionException, InterruptedException {
 2         /** 2.非典型用法:異步轉換 */
 3         // 異步轉換,參數1是須要轉換的listenableFuture,參數2是轉換方法,參數3是執行轉換的線程執行器(Runnable)。
 4         ListenableFuture<Integer> transform = Futures.transformAsync(callableListenableFuture1, new AsyncFunction<String, Integer>() {
 5             @Override
 6             public ListenableFuture<Integer> apply(@Nullable String input) {
 7                 return Futures.immediateFuture(Integer.parseInt(input));
 8             }
 9         }, MoreExecutors.directExecutor());
10         // 阻塞線程獲得結果
11         System.out.println("阻塞獲取轉換後任務的結果:"+transform.get());
12 }

打印結果:

阻塞獲取轉換後任務的結果:1

2.1.3 多線程併發執行取結果集合

實現功能:

1)定義多個任務

2)調用Futures工具類的allAsList方法合併結果,返回一個總ListenableFuture,調用get方法便可實現多線程併發執行任務取結果集合,結果是list,順序是按照提交任務的順序。

源碼以下:

 1 public static void main(String[] args) throws ExecutionException, InterruptedException {
 2         /** 3.典型用法:多任務併發執行取結果list */
 3         // 可監聽不帶返回值的任務
 4 
 5         ListenableFuture<String> callableListenableFuture2 = listeningExecutorService.submit(() -> {
 6             Thread.sleep(3000);
 7             System.out.println("callable2 call!");
 8             return "2";
 9         });
10         ListenableFuture<String> callableListenableFuture3 = listeningExecutorService.submit(() -> {
11             System.out.println("callable3 call!");
12             return "3";
13         });
14         ListenableFuture<List<String>> listListenableFuture = Futures.allAsList(
15             Lists.newArrayList(callableListenableFuture1, callableListenableFuture2, callableListenableFuture3));
16         // 返回結果list就是添加任務的順序
17         System.out.println("多任務併發執行取結果list result=" + listListenableFuture.get());
18 }

打印結果:

callable1 call!
callable3 call! callable2 call! 多任務併發執行取結果list result=[1, 2, 3]

2.2 Service框架

Guava包裏的Service接口用於封裝一個服務對象的運行狀態,包括start和stop等方法。例如web服務器,RPC服務器、計時器等能夠實現這個接口。對此類服務的狀態管理在多線程環境下尤其複雜。Guava包提供了一些基礎類幫助你管理複雜的狀態轉換邏輯和同步細節。這裏不細節拓展,不多狀況會用到這個框架。

3、總結

Guava 提供了ListenableFuture接口,結合Futures工具類,能夠很是方便的實現併發任務,取結果list等方法,且API優雅易用,在特定場景,建議使用。

相反,Service框架,可能重量級的業務場景纔可能使用到,簡單場景沒有必要使用。

相關文章
相關標籤/搜索