使用guava實現(xiàn)異步回調(diào)
guava介紹
guava
是google針對java異步調(diào)用任務(wù)的加強框架,它與Java的FutureTask的區(qū)別如下
- 1.FutureTask是主動調(diào)用的模式,“調(diào)用線程”會主動獲取異步結(jié)果,在獲取得到結(jié)果之前一直都保持這阻塞的狀態(tài),并且會一直阻塞,直到拿到異步調(diào)用的結(jié)果。
- 2.Guava是異步回調(diào)模式,“調(diào)用線程”不會主動獲取異步結(jié)果,而是通過被調(diào)用線程執(zhí)行回調(diào)鉤子函數(shù),“調(diào)用線程”在執(zhí)行完自己的邏輯之后就結(jié)束了,當(dāng)回調(diào)函數(shù)執(zhí)行時,可能“調(diào)用函數(shù)”已經(jīng)停止很久了
FutureTask的異步調(diào)用模式簡單demo代碼
public class javaFutureDemo {
public static final int SLEEP_GAP = 500;
public static String getCurThreadName(){
return Thread.currentThread().getName();
}
static class BoilWaterThread implements Callable<Boolean> {
@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<Boolean> {
@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<Boolean> bJob = new BoilWaterThread();
FutureTask<Boolean> bTask = new FutureTask<>(bJob);
Thread bThread = new Thread(bTask,"燒水線程");
Callable<Boolean> cJob = new CleanCupThread();
FutureTask<Boolean> 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異步回調(diào)流程
異步回調(diào)流程
- 1.實現(xiàn)Java的Callable接口,創(chuàng)建異步執(zhí)行邏輯,如果是不需要返回值,那么也可以實現(xiàn)Runnable接口
- 2.創(chuàng)建Guava線程池
- 3.將(1)中創(chuàng)建的Callable/Runnable異步執(zhí)行的邏輯的實例提交到guava線程池,從而獲得listenableFuture異步任務(wù)實例
- 4.創(chuàng)建FutureCallable回調(diào)實例,通過Futures.addCallableback將回調(diào)實例綁定到ListenableFuture異步任務(wù)上。
guava異步回調(diào)實現(xiàn)demo
public class GuavaFutureDemo {
public static final int SLEEP_GAP = 3000;
static class BoilWaterThread implements Callable<Boolean> {
@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<Boolean> {
@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();
//燒水的業(yè)務(wù)邏輯
Callable<Boolean> bJob = new BoilWaterThread();
//洗杯子的業(yè)務(wù)邏輯
Callable<Boolean> cJob = new CleanThread();
//創(chuàng)建java線程池
ExecutorService jPool = Executors.newFixedThreadPool(10);
//構(gòu)造guava線程
ListeningExecutorService gPool = MoreExecutors.listeningDecorator(jPool);
//燒水的回調(diào)鉤子
FutureCallback<Boolean> hotWaterHook = new FutureCallback<Boolean>() {
@Override
public void onSuccess(Boolean aBoolean) {
if(aBoolean){
drinkJob.waterOK = true;
//執(zhí)行回調(diào)方法
drinkJob.drinkTea();
}
}
@Override
public void onFailure(Throwable throwable) {
System.out.println("燒水失敗了,沒有茶喝了");
}
};
//啟動燒水線程
ListenableFuture<Boolean> hotFuture = gPool.submit(bJob);
//設(shè)置燒水任務(wù)的回調(diào)鉤子
Futures.addCallback(hotFuture,hotWaterHook);
//啟動清洗線程
ListenableFuture<Boolean> washFuture = gPool.submit(cJob);
//使用匿名實例,作為清洗之后的回調(diào)函數(shù)
Futures.addCallback(washFuture, new FutureCallback<Boolean>() {
@Override
public void onSuccess(Boolean aBoolean) {
if(aBoolean){
drinkJob.cupOK = true;
//執(zhí)行回調(diào)方法
drinkJob.drinkTea();
}
}
@Override
public void onFailure(Throwable throwable) {
System.out.println("杯子洗不了,沒有茶喝了");
}
});
}
}