使用guava实现异步回调
guava介绍
guava
是google针对java异步调用任务的加强框架,它与Java的FutureTask的区别如下
- 1.FutureTask是主动调用的模式,“调用线程”会主动获取异步结果,在获取得到结果之前一直都保持这阻塞的状态,并且会一直阻塞,直到拿到异步调用的结果。
- 2.Guava是异步回调模式,“调用线程”不会主动获取异步结果,而是通过被调用线程执行回调钩子函数,“调用线程”在执行完自己的逻辑之后就结束了,当回调函数执行时,可能“调用函数”已经停止很久了
FutureTask的异步调用模式简单demo代码
public class javaFutureDemo {
public static final int SLEEP_GAP = 500;
public static String getCurThreadName(){
return Thread.currentThread().getName();
}
static class BoilWaterThread implements Callable {
@Override
public Boolean call() {
try {
System.out.println("清洗水瓶");
System.out.println("灌上凉水");
System.out.println("烧开水");
Thread.sleep(SLEEP_GAP);
System.out.println("水开了");
return true;
}catch (Exception e){
e.printStackTrace();
return false;
}
}
}
static class CleanCupThread implements Callable {
@Override
public Boolean call() {
try{
System.out.println("洗杯子");
System.out.println("洗茶具");
Thread.sleep(SLEEP_GAP);
System.out.println("洗好了");
return true;
}catch (Exception e){
e.printStackTrace();
return false;
}
}
}
public static void drinkTea(Boolean waterOk,Boolean cupOk){
if(waterOk && cupOk){
System.out.println("泡茶喝");
}else if(!waterOk){
System.out.println("水没烧开,泡不了茶");
}else if(!cupOk){
System.out.println("杯子没有洗好,泡不了茶");
}
}
public static void main(String[] args) {
Callable bJob = new BoilWaterThread();
FutureTask bTask = new FutureTask<>(bJob);
Thread bThread = new Thread(bTask,"烧水线程");
Callable cJob = new CleanCupThread();
FutureTask cTask = new FutureTask<>(cJob);
Thread cThread = new Thread(cTask,"清洗杯子线程");
bThread.start();
cThread.start();
try{
Boolean waterOk = bTask.get();
Boolean cupOk = cTask.get();
drinkTea(waterOk,cupOk);
}catch (Exception e){
e.printStackTrace();
}
System.out.println("泡好茶了");
}
}
guava异步回调流程
异步回调流程
- 1.实现Java的Callable接口,创建异步执行逻辑,如果是不需要返回值,那么也可以实现Runnable接口
- 2.创建Guava线程池
- 3.将(1)中创建的Callable/Runnable异步执行的逻辑的实例提交到guava线程池,从而获得listenableFuture异步任务实例
- 4.创建FutureCallable回调实例,通过Futures.addCallableback将回调实例绑定到ListenableFuture异步任务上。
guava异步回调实现demo
public class GuavaFutureDemo {
public static final int SLEEP_GAP = 3000;
static class BoilWaterThread implements Callable {
@Override
public Boolean call() {
try {
System.out.println("清洗水瓶");
System.out.println("灌上凉水");
System.out.println("烧开水");
Thread.sleep(SLEEP_GAP-1000);
System.out.println("水开了");
return true;
}catch (Exception e){
e.printStackTrace();
return false;
}
}
}
static class CleanThread implements Callable {
@Override
public Boolean call() {
try {
System.out.println("清洗水瓶");
System.out.println("清茶具");
Thread.sleep(SLEEP_GAP);
System.out.println("洗好了");
return true;
}catch (Exception e){
e.printStackTrace();
return false;
}
}
}
static class DrinkJob{
boolean waterOK = false;
boolean cupOK = false;
public void drinkTea(){
if(waterOK && cupOK){
System.out.println("泡茶喝,茶喝完");
// this.waterOK = false;
}
}
}
public static void main(String[] args) {
Thread.currentThread().setName("泡茶喝线程");
//新起一个线程,作为泡茶主线程
DrinkJob drinkJob = new DrinkJob();
//烧水的业务逻辑
Callable bJob = new BoilWaterThread();
//洗杯子的业务逻辑
Callable cJob = new CleanThread();
//创建java线程池
ExecutorService jPool = Executors.newFixedThreadPool(10);
//构造guava线程
ListeningExecutorService gPool = MoreExecutors.listeningDecorator(jPool);
//烧水的回调钩子
FutureCallback hotWaterHook = new FutureCallback() {
@Override
public void onSuccess(Boolean aBoolean) {
if(aBoolean){
drinkJob.waterOK = true;
//执行回调方法
drinkJob.drinkTea();
}
}
@Override
public void onFailure(Throwable throwable) {
System.out.println("烧水失败了,没有茶喝了");
}
};
//启动烧水线程
ListenableFuture hotFuture = gPool.submit(bJob);
//设置烧水任务的回调钩子
Futures.addCallback(hotFuture,hotWaterHook);
//启动清洗线程
ListenableFuture washFuture = gPool.submit(cJob);
//使用匿名实例,作为清洗之后的回调函数
Futures.addCallback(washFuture, new FutureCallback() {
@Override
public void onSuccess(Boolean aBoolean) {
if(aBoolean){
drinkJob.cupOK = true;
//执行回调方法
drinkJob.drinkTea();
}
}
@Override
public void onFailure(Throwable throwable) {
System.out.println("杯子洗不了,没有茶喝了");
}
});
}
}