自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Java中的回調(diào)機制,這篇給你整的明明白白的

開發(fā) 后端
在一個應用系統(tǒng)中, 無論使用何種語言開發(fā), 必然存在模塊之間的調(diào)用, 調(diào)用的方式分為幾種,來看一下吧。

調(diào)用和回調(diào)機制

在一個應用系統(tǒng)中, 無論使用何種語言開發(fā), 必然存在模塊之間的調(diào)用, 調(diào)用的方式分為幾種:

1.同步調(diào)用

同步調(diào)用是最基本并且最簡單的一種調(diào)用方式, 類A的方法a()調(diào)用類B的方法b(), 一直等待b()方法執(zhí)行完畢, a()方法繼續(xù)往下走. 這種調(diào)用方式適用于方法b()執(zhí)行時間不長的情況, 因為b()方法執(zhí)行時間一長或者直接阻塞的話, a()方法的余下代碼是無法執(zhí)行下去的, 這樣會造成整個流程的阻塞.

2.異步調(diào)用

異步調(diào)用是為了解決同步調(diào)用可能出現(xiàn)阻塞, 導致整個流程卡住而產(chǎn)生的一種調(diào)用方式. 類A的方法方法a()通過新起線程的方式調(diào)用類B的方法b(), 代碼接著直接往下執(zhí)行, 這樣無論方法b()執(zhí)行時間多久, 都不會阻塞住方法a()的執(zhí)行.

但是這種方式, 由于方法a()不等待方法b()的執(zhí)行完成, 在方法a()需要方法b()執(zhí)行結(jié)果的情況下(視具體業(yè)務而定, 有些業(yè)務比如啟異步線程發(fā)個微信通知、刷新一個緩存這種就沒必要), 必須通過一定的方式對方法b()的執(zhí)行結(jié)果進行監(jiān)聽.

在Java中, 可以使用Future+Callable的方式做到這一點, 具體做法可以參見文章:

http://www.cnblogs.com/xrq730/p/4872722.html

3.回調(diào)

如下圖所示, 回調(diào)是一種雙向的調(diào)用方式, 其實而言, 回調(diào)也有同步和異步之分, 講解中是同步回調(diào), 第二個例子使用的是異步回調(diào)

回調(diào)的思想是:

  •  類A的a()方法調(diào)用類B的b()方法
  •  類B的b()方法執(zhí)行完畢主動調(diào)用類A的callback()方法

通俗而言: 就是A類中調(diào)用B類中的某個方法C, 然后B類中反過來調(diào)用A類中的方法D, D這個方法就叫回調(diào)方法, 這樣子說你是不是有點暈暈的, 其實我剛開始也是這樣不理解, 看了人家說比較經(jīng)典的回調(diào)方式:

  1.  class A實現(xiàn)接口CallBack callback——背景1
  2.  class A中包含一個class B的引用b ——背景2
  3.  class B有一個參數(shù)為callback的方法f(CallBack callback) ——背景3
  4.  A的對象a調(diào)用B的方法 f(CallBack callback) ——A類調(diào)用B類的某個方法 C
  5.  然后b就可以在f(CallBack callback)方法中調(diào)用A的方法 ——B類調(diào)用A類的某個方法D

回調(diào)的種類

回調(diào)分為同步回調(diào)和異步回調(diào), 假如以買彩票的場景來模擬, 我買彩票, 調(diào)用彩票網(wǎng),給我返回的結(jié)果確定是否中獎,同步回調(diào)就是,我買了彩票之后, 需要等待彩票網(wǎng)給我返回的結(jié)果, 這個時候我不能做其他事情, 我必須等待這個結(jié)果, 這就叫同步回調(diào), 同步, 就意味著等待, 我不能去做其他事情, 必須等待。

異步回調(diào)就是, 我買了彩票之后, 可以去做其他事情, 然后當彩票網(wǎng)有了結(jié)果和消息, 再給我返回消息, 其中最明顯的方式就是在得到彩票結(jié)果的函數(shù)之中, 添加一個其他的方法, 如果我的其他方法可以立即執(zhí)行, 那么就是異步的(給出是否中獎需要花費很長的時間), 而在測試函數(shù)之中, 前后兩個, 那是發(fā)生在測試函數(shù)的線程之中的, 肯定是一前一后按照次序的, 在這個地方不是顯示同步異步的地點.

同步回調(diào)

同步回調(diào)和異步回調(diào), 主要體現(xiàn)在其是否需要等待. 同步調(diào)用, 如果被調(diào)用一方的APi(第三方API), 處理問題需要花很長時間, 我們需要等待, 那就是同步回調(diào), 如果調(diào)用完之后不需要理解得到結(jié)果, 我們調(diào)完就走, 去做其他事情, 那就是異步調(diào)用, 異步調(diào)用需要在我們調(diào)用第三方API處, 開啟一個新的線程即可, 而同步調(diào)用和平常的調(diào)用沒有任何區(qū)別.

例子

OrderResult接口, 其中的方法getOrderResult 

  1. public interface OrderResult {  
  2.     /**  
  3.      * 訂購貨物的狀態(tài)  
  4.      *  
  5.      * @param state  
  6.      * @return  
  7.      */  
  8.     //參數(shù)可以不用, 用不用按照自己的實際需求決定  
  9.     public String getOrderResult(String state);  

Store類, 商店提供會無預定消息返回的接口, 回調(diào)OrderResult接口的方法, 給其返回預訂商品的狀態(tài), 重點是returnOrderGoodsInfo(OrderResult order)方法, 體現(xiàn)了回調(diào)的回. Store是被調(diào)用的一方, 被調(diào)用的一方, 要回過去調(diào)用調(diào)用一方的方法, 這個方法實際上是回調(diào)接口的方法. 

  1. public class Store {  
  2.     @Getter  
  3.     @Setter  
  4.     private String name;  
  5.     Store(String name) {  
  6.         this.name = name;  
  7.     } 
  8.     /*回調(diào)函數(shù), 將結(jié)構傳給那個我們不能直接調(diào)用的方法, 然后獲取結(jié)果*/  
  9.     public String returnOrderGoodsInfo(OrderResult order) {  
  10.         String[] s = {"訂購中...", "訂購失敗", "即將發(fā)貨!", "運輸途中...", "已在投遞"};  
  11.         Random random = new Random();  
  12.         int temp = random.nextInt(5);  
  13.         String ss1 = s[temp];  
  14.         return order.getOrderResult(s1);  
  15.     }  

SyncBuyer類, 同步顧客類, 其中獲取商品的訂購狀態(tài),orderGoods(), 調(diào)用了store返回商品調(diào)用信息的returnOrderGoodsInfo()方法, 但是在Store類的returnOrderGoodsInfo()方法之中, 以OrderResult接口為參數(shù), 反過來調(diào)用了OrderResult接口, 相當于調(diào)用了其子類SyncBuyer本身, 以他為參數(shù), 調(diào)用了getOrderResult(String state)方法, 也就是OrderResult接口的方法, 相當于就完成了一個調(diào)用的循環(huán), 然后取到了我們自己無法給出的結(jié)果.

這個地方的"循環(huán)", 是回調(diào)的關鍵所在, 需要正常調(diào)用其他外接提供方法來獲取結(jié)果的一方, 繼承一個回調(diào)接口, 實現(xiàn)它, 然后調(diào)用第三方的API方法, 第三方在我們調(diào)用的方法之中, 以回調(diào)結(jié)構為參數(shù), 然后調(diào)用了接口中的方法, 其中可以返回相應的結(jié)果給我們.

需要說明的是, 我們雖然實現(xiàn)了這個接口的方法, 但是我們自己的類之中, 或者說此類本身, 卻沒法調(diào)用這個方法, 也可以說, 此類調(diào)用這個方法是不會產(chǎn)生有效的結(jié)果的. 回調(diào)的回, 就體現(xiàn)在此處, 在Store類之中的returnOrderGoodsInfo(OrderResult order)方法之中, 得到了很好的體現(xiàn). 

  1. /*同步, 顧客在商店預訂商品, 商店通知顧客預訂情況*/  
  2. public class SyncBuyer implements OrderResult {  
  3.     @Getter  
  4.     @Setter  
  5.     private Store store;//商店  
  6.     @Getter  
  7.     @Setter  
  8.     private String buyerName;//購物者名  
  9.     @Getter  
  10.     @Setter  
  11.     private String goodsName;//所購商品名  
  12.     SyncBuyer(Store store, String buyerName, String goodsName) {  
  13.         this.store = store;  
  14.         this.buyerName = buyerName;  
  15.         this.goodsName = goodsName;  
  16.     }  
  17.     /*調(diào)用從商店返回訂購物品的信息*/  
  18.     public String orderGoods() {  
  19.         String goodsState = store.returnOrderGoodsInfo(this);  
  20.         System.out.println(goodsState);  
  21.         myFeeling();// 測試同步還是異步, 同步需要等待, 異步無需等待  
  22.         return goodsState;  
  23.     }  
  24.     public void myFeeling() { 
  25.          String[] s = {"有點小激動", "很期待!", "希望是個好貨!"};  
  26.         Random random = new Random();  
  27.         int temp = random.nextInt(3);  
  28.         System.out.println("我是" + this.getBuyerName() + ", 我現(xiàn)在的感覺: " + s[temp]);  
  29.     }  
  30.     /*被回調(diào)的方法, 我們自己不去調(diào)用, 這個方法給出的結(jié)果, 是其他接口或者程序給我們的, 我們自己無法產(chǎn)生*/  
  31.     @Override  
  32.     public String getOrderResult(String state) {  
  33.         return "在" + this.getStore().getName() + "商店訂購的" + this.getGoodsName() + "玩具, 目前的預訂狀態(tài)是: " + state;  
  34.     }  

Test2Callback類, 測試同步回調(diào)的結(jié)果, 

  1. public class Test2Callback {  
  2.     public static void main(String[] args) {  
  3.         Store wallMart = new Store("沙中路沃爾瑪");  
  4.         SyncBuyer syncBuyer = new SyncBuyer(wallMart, "小明", "超能鐵扇公主");  
  5.         System.out.println(syncBuyer.orderGoods());  
  6.     }  

異步回調(diào)

同步回調(diào)和異步回調(diào)的代碼層面的差別就是是否在我們調(diào)用第三方的API處, 為其開辟一條新的線程, 其他并無差異。Java知音公眾號內(nèi)回復”面試題聚合“,送你一份面試題寶典

例子

OrderResult接口, 其中的方法getOrderResult 

  1. public interface OrderResult {  
  2.     /**  
  3.      * 訂購貨物的狀態(tài)  
  4.      *  
  5.      * @param state  
  6.      * @return  
  7.      */  
  8.     //參數(shù)可以不用, 用不用按照自己的實際需求決定  
  9.     public String getOrderResult(String state);  

Store類, 商店提供會無預定消息返回的接口, 回調(diào)OrderResult接口的方法, 給其返回預訂商品的狀態(tài). 

  1. public class Store {  
  2.     @Getter  
  3.     @Setter  
  4.     private String name;  
  5.     Store(String name) {  
  6.         this.name = name;  
  7.     }  
  8.     /*回調(diào)函數(shù), 將結(jié)構傳給那個我們不能直接調(diào)用的方法, 然后獲取結(jié)果*/  
  9.     public String returnOrderGoodsInfo(OrderResult order) {  
  10.         String[] s = {"訂購中...", "訂購失敗", "即將發(fā)貨!", "運輸途中...", "已在投遞"};  
  11.         Random random = new Random();  
  12.         int temp = random.nextInt(5);  
  13.         String ss1 = s[temp];  
  14.         return order.getOrderResult(s1);  
  15.     }  

NoSyncBuyer類, 異步調(diào)用Store類的returnOrderGoodsInfo(OrderResult order)方法, 來返回商品轉(zhuǎn)改的結(jié)果. 

  1. /*異步*/  
  2. @Slf4j  
  3. public class NoSyncBuyer implements OrderResult {  
  4.     @Getter  
  5.     @Setter  
  6.     private Store store;//商店  
  7.     @Getter  
  8.     @Setter  
  9.     private String buyerName;//購物者名  
  10.     @Getter  
  11.     @Setter  
  12.     private String goodsName;//所購商品名  
  13.     NoSyncBuyer(Store store, String buyerName, String goodsName) {  
  14.         this.store = store;  
  15.         this.buyerName = buyerName;  
  16.         this.goodsName = goodsName;  
  17.     }  
  18.     /*調(diào)用從商店返回訂購物品的信息*/  
  19.     public String orderGoods() {  
  20.         String goodsState = "--" 
  21.         MyRunnable mr = new MyRunnable();  
  22.         Thread t = new Thread(mr);  
  23.         t.start();  
  24.         System.out.println(goodsState);  
  25.         goodsState = mr.getResult();// 得到返回值  
  26.         myFeeling();// 用來測試異步是不是還是按順序的執(zhí)行  
  27.         return goodsState; 
  28.     }  
  29.     public void myFeeling() {  
  30.         String[] s = {"有點小激動", "很期待!", "希望是個好貨!"}; 
  31.         Random random = new Random();  
  32.         int temp = random.nextInt(3);  
  33.         System.out.println("我是" + this.getBuyerName() + ", 我現(xiàn)在的感覺: " + s[temp]);  
  34.     }  
  35.     /*被回調(diào)的方法, 我們自己不去調(diào)用, 這個方法給出的結(jié)果, 是其他接口或者程序給我們的, 我們自己無法產(chǎn)生*/  
  36.     @Override  
  37.     public String getOrderResult(String state) {  
  38.         return "在" + this.getStore().getName() + "商店訂購的" + this.getGoodsName() + "玩具, 目前的預訂狀態(tài)是: " + state;  
  39.     }  
  40.     // 開啟另一個線程, 但是沒有返回值, 怎么回事  
  41.     // 調(diào)試的時候, 等待一會兒, 還是可以取到值, 但不是立即取到, 在print顯示的時候, 卻是null, 需要注意?  
  42.     private class MyRunnable implements Runnable {  
  43.         @Getter  
  44.         @Setter  
  45.         private String result; 
  46.         @Override  
  47.         public void run() {  
  48.             try {  
  49.                 Thread.sleep(10000);  
  50.                 result = store.returnOrderGoodsInfo(NoSyncBuyer.this);// 匿名函數(shù)的時候, 無法return 返回值  
  51.             } catch (InterruptedException e) {  
  52.                 log.error("出大事了, 異步回調(diào)有問題了", e);  
  53.             }  
  54.         }  
  55.     }  

Test2Callback類, 測試同步回調(diào)和異步回調(diào)的結(jié)果. 

  1. public class Test2Callback {  
  2.     public static void main(String[] args) {  
  3.         Store wallMart = new Store("沙中路沃爾瑪");  
  4.         SyncBuyer syncBuyer = new SyncBuyer(wallMart, "小明", "超能鐵扇公主");  
  5.         System.out.println(syncBuyer.orderGoods());  
  6.         System.out.println("\n");  
  7.         Store lawson = new Store("沙中路羅森便利店");  
  8.         NoSyncBuyer noSyncBuyer = new NoSyncBuyer(lawson, "cherry", "變形金剛");  
  9.         System.out.println(noSyncBuyer.orderGoods());  
  10.     }  
  11.  

 

責任編輯:龐桂玉 來源: Java知音
相關推薦

2021-09-30 09:59:23

OSPF網(wǎng)絡協(xié)議網(wǎng)絡技術

2011-11-04 16:49:26

Action BarAndroid

2011-04-27 17:05:39

2010-09-06 17:35:03

PPPOE配置

2020-02-10 19:42:01

CPIP 協(xié)議,

2021-02-23 08:10:18

Nginx反向代理負載均衡器

2021-09-26 07:38:39

組合問題數(shù)據(jù)結(jié)構算法

2010-06-29 14:38:14

Linux服務器

2010-08-03 09:17:00

2010-07-05 15:33:49

2010-10-08 15:05:00

無線路由設置

2012-02-20 21:59:08

無線路由設置

2010-09-09 09:52:03

Linux服務器

2010-07-14 09:55:12

2010-08-25 09:09:58

2010-10-15 10:01:19

無線網(wǎng)絡構建

2010-08-06 10:00:05

負載均衡

2020-11-18 09:25:39

Docker

2020-12-22 10:57:36

DockerLinux程序員

2022-04-20 11:03:28

Linux內(nèi)存管理
點贊
收藏

51CTO技術棧公眾號