一、说明:
1、装饰Concurrent包里的ExecutorService
ListeningExecutorService guavaExecutor = MoreExecutors
.listeningDecorator(Executors.newSingleThreadExecutor());
2、ListenableFuture的创建
final ListenableFuture listenableFuture = guavaExecutor
.submit(new Callable() {
。。。。。。
});
3、ListenableFuture注册监听器,即异步调用完成时会在指定的线程池中执行注册的监听器
listenableFuture.addListener(new Runnable() {
。。。。。。
}, Executors.newSingleThreadExecutor());
Futures.addCallback(listenableFuture2, new FutureCallback() {
@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 nativeFuture = nativeExecutor
.submit(new Callable() {
@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 listenableFuture = guavaExecutor
.submit(new Callable() {
@Override
public String call() throws Exception {
TimeUnit.SECONDS.sleep(1);
return "[" + Thread.currentThread().getName() +"]: guava的Future返回结果";
}
});
// 注册监听器,即异步调用完成时会在指定的线程池中执行注册的监听器
listenableFuture.addListener(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 listenableFuture2 = guavaExecutor2
.submit(new Callable() {
@Override
public String call() throws Exception {
TimeUnit.SECONDS.sleep(1);
String logText = "[" + Thread.currentThread().getName() +"]: guava的Future返回结果";
System.out.println(logText);
return logText;
}
});
// 注意这里没用指定执行回调的线程池,从输出可以看出,默认是和执行异步操作的线程是同一个.
Futures.addCallback(listenableFuture2, new FutureCallback() {
@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
四、总结:
略。