Guava併發(3)——實現的非同步回撥
阿新 • • 發佈:2019-02-11
一、說明:
1、裝飾Concurrent包裡的ExecutorService
ListeningExecutorService guavaExecutor = MoreExecutors
.listeningDecorator(Executors.newSingleThreadExecutor());
2、ListenableFuture的建立
3、ListenableFuture註冊監聽器,即非同步呼叫完成時會在指定的執行緒池中執行註冊的監聽器final ListenableFuture<T> listenableFuture = guavaExecutor .submit(new Callable<T>() { 。。。。。。 });
listenableFuture.addListener(new Runnable() {
。。。。。。
}, Executors.newSingleThreadExecutor());
4、Futures方法進行Callback
Futures.addCallback(listenableFuture2, new FutureCallback<T>() { @Override public void onSuccess(Tresult) { 。。。。。。 } @Override public void onFailure(Throwable t) { } } );
二、程式碼:
package com.wll.guava.concurrent; import com.google.common.util.concurrent.*; import java.util.concurrent.*; /** * 使用guava實現非同步回撥 {@link java.util.concurrent.Future} * {@link com.google.common.util.concurrent.ListenableFuture} * {@link com.google.common.util.concurrent.FutureCallback} * * @author landon */ public class FutureCallbackExample { public static void main(String[] args) throws Exception { nativeFuture(); Thread.sleep(3000L); guavaFuture(); Thread.sleep(3000L); guavaFuture2(); } public static void nativeFuture() throws Exception { // 原生的Future模式,實現非同步 ExecutorService nativeExecutor = Executors.newSingleThreadExecutor(); Future<String> nativeFuture = nativeExecutor .submit(new Callable<String>() { @Override public String call() throws Exception { // 使用sleep模擬呼叫耗時 TimeUnit.SECONDS.sleep(1); return "[" + Thread.currentThread().getName() +"]: 併發包Future返回結果" ; } }); // Future只實現了非同步,而沒有實現回撥.所以此時主執行緒get結果時阻塞.或者可以輪訓以便獲取非同步呼叫是否完成 System.out.println("[" + Thread.currentThread().getName() +"]====>"+ nativeFuture.get()); } public static void guavaFuture() throws Exception { System.out.println("-------------------------------- 神祕的分割線 -----------------------------------"); // 好的實現應該是提供回撥,即非同步呼叫完成後,可以直接回調.本例採用guava提供的非同步回撥介面,方便很多. ListeningExecutorService guavaExecutor = MoreExecutors .listeningDecorator(Executors.newSingleThreadExecutor()); final ListenableFuture<String> listenableFuture = guavaExecutor .submit(new Callable<String>() { @Override public String call() throws Exception { TimeUnit.SECONDS.sleep(1); return "[" + Thread.currentThread().getName() +"]: guava的Future返回結果"; } }); // 註冊監聽器,即非同步呼叫完成時會在指定的執行緒池中執行註冊的監聽器 listenableFuture.<span style="color:#FF0000;">addListener</span>(new Runnable() { @Override public void run() { try { String logTxt = "[" + Thread.currentThread().getName() +"]: guava對返回結果進行非同步CallBack(Runnable):" + listenableFuture.get(); System.out.println(logTxt); } catch (Exception e) { } } }, Executors.newSingleThreadExecutor()); // 主執行緒可以繼續執行,非同步完成後會執行註冊的監聽器任務. System.out.println( "[" + Thread.currentThread().getName() +"]: guavaFuture1執行結束"); } public static void guavaFuture2() throws Exception { System.out.println("-------------------------------- 神祕的分割線 -----------------------------------"); // 除了ListenableFuture,guava還提供了FutureCallback介面,相對來說更加方便一些. ListeningExecutorService guavaExecutor2 = MoreExecutors .listeningDecorator(Executors.newSingleThreadExecutor()); final ListenableFuture<String> listenableFuture2 = guavaExecutor2 .submit(new Callable<String>() { @Override public String call() throws Exception { TimeUnit.SECONDS.sleep(1); String logText = "[" + Thread.currentThread().getName() +"]: guava的Future返回結果"; System.out.println(logText); return logText; } }); // 注意這裡沒用指定執行回撥的執行緒池,從輸出可以看出,<span style="color:#FF0000;">預設是和執行非同步操作的執行緒是同一個.</span> Futures.addCallback(listenableFuture2, new FutureCallback<String>() { @Override public void onSuccess(String result) { String logTxt = "[" + Thread.currentThread().getName() +"]=======>對回撥結果【"+result+"】進行FutureCallback,經測試,發現是和回撥結果處理執行緒為同一個執行緒"; System.out.println(logTxt); } @Override public void onFailure(Throwable t) { } } ); // 主執行緒可以繼續執行,非同步完成後會執行註冊的監聽器任務. System.out.println( "[" + Thread.currentThread().getName() +"]: guavaFuture2執行結束"); } }
三、執行結果
D:\DevPro\Java\jdk1.7.0_79\bin\java -agentlib:jdwp=transport=dt_socket,address=127.0.0.1:62193,suspend=y,server=n -Dfile.encoding=UTF-8 -classpath "D:\DevPro\Java\jdk1.7.0_79\jre\lib\jce.jar;D:\DevPro\Java\jdk1.7.0_79\jre\lib\jfr.jar;D:\DevPro\Java\jdk1.7.0_79\jre\lib\management-agent.jar;D:\DevPro\Java\jdk1.7.0_79\jre\lib\resources.jar;D:\DevPro\Java\jdk1.7.0_79\jre\lib\charsets.jar;D:\DevPro\Java\jdk1.7.0_79\jre\lib\javaws.jar;D:\DevPro\Java\jdk1.7.0_79\jre\lib\deploy.jar;D:\DevPro\Java\jdk1.7.0_79\jre\lib\plugin.jar;D:\DevPro\Java\jdk1.7.0_79\jre\lib\jsse.jar;D:\DevPro\Java\jdk1.7.0_79\jre\lib\rt.jar;D:\DevPro\Java\jdk1.7.0_79\jre\lib\jfxrt.jar;D:\DevPro\Java\jdk1.7.0_79\jre\lib\ext\access-bridge-64.jar;D:\DevPro\Java\jdk1.7.0_79\jre\lib\ext\dnsns.jar;D:\DevPro\Java\jdk1.7.0_79\jre\lib\ext\jaccess.jar;D:\DevPro\Java\jdk1.7.0_79\jre\lib\ext\sunec.jar;D:\DevPro\Java\jdk1.7.0_79\jre\lib\ext\sunjce_provider.jar;D:\DevPro\Java\jdk1.7.0_79\jre\lib\ext\sunmscapi.jar;D:\DevPro\Java\jdk1.7.0_79\jre\lib\ext\zipfs.jar;D:\DevPro\Java\jdk1.7.0_79\jre\lib\ext\localedata.jar;E:\DevCode\guavaLearn\target\classes;C:\Users\Administrator\.m2\repository\com\google\guava\guava\18.0\guava-18.0.jar;C:\Users\Administrator\.m2\repository\org\mockito\mockito-all\2.0.2-beta\mockito-all-2.0.2-beta.jar;C:\Users\Administrator\.m2\repository\junit\junit\4.12\junit-4.12.jar;C:\Users\Administrator\.m2\repository\org\hamcrest\hamcrest-core\1.3\hamcrest-core-1.3.jar;C:\Users\Administrator\.m2\repository\com\alibaba\fastjson\1.2.7\fastjson-1.2.7.jar;D:\DevPro\JetBrains\IntelliJ IDEA 14.0.2\lib\idea_rt.jar" com.wll.guava.concurrent.FutureCallbackExample
Connected to the target VM, address: '127.0.0.1:62193', transport: 'socket'
[main]====>[pool-1-thread-1]: 併發包Future返回結果
-------------------------------- 神祕的分割線 -----------------------------------
[main]: guavaFuture1執行結束
[pool-3-thread-1]: guava對返回結果進行非同步CallBack(Runnable):[pool-2-thread-1]: guava的Future返回結果
-------------------------------- 神祕的分割線 -----------------------------------
[main]: guavaFuture2執行結束
[pool-4-thread-1]: guava的Future返回結果
[pool-4-thread-1]=======>對回撥結果【[pool-4-thread-1]: guava的Future返回結果】進行FutureCallback,經測試,發現是和回撥結果處理執行緒為同一個執行緒
Disconnected from the target VM, address: '127.0.0.1:62193', transport: 'socket'
Process finished with exit code -1
四、總結:
略。