java 的函數回調

本文的目的並不是介紹使用的什麼技術,而是重點闡述其實現原理。

 

一、 異步和同步

講通俗點,異步就是不需要等當前執行的動作完成,就可以繼續執行後面的動作。

 

通常一個程序執行的順序是:從上到下,依次執行。後面的動作必須等前面動作執行完成以後方可執行。這就是和異步相對的一個概念——同步。

 

案例:

A、張三打電話給李四,讓李四幫忙寫份材料。

B、李四接到電話的時候,手上有自己的工作要處理,但他答應張三,忙完手上的工作後馬上幫張三寫好材料,並傳真給張三。

C、通完電話後,張三外出辦事。

 

說明:

張三給李四通完電話後,就出去辦事了,他並不需要等李四把材料寫好才外出。那麼張三讓李四寫材料的消息就屬於異步消息。

相反,如果張三必須等李四把材料寫好才能外出辦事的話,那麼這個消息就屬於同步消息了。

 

二、 異步的實現

傳統的程序執行代碼都是從上到下,一條一條執行的。

但生活中有很多情況並不是這樣,以上的案例中,如果李四需要幾個小時以後才能幫張三寫好材料的話,那張三就必須等幾個小時,這樣張三可能會崩潰或者抓狂。

 

這種一條龍似的處理,顯示不太合理。

 

可以使用以下辦法來處理這種問題:

張三找王五去給李四打電話,等李四寫好材料後,由王五轉交給張三。這樣張三就可以外出辦其他的事情了。

 

問題得到了合理的解決,之前張三一條線的工作,由張三和王五兩條線來完成了,兩邊同時進行,彼此不耽誤。

 

三、 計算機語言的實現

辦法有了,如何用程序來模擬實現呢?

 

A、以前由一個線程來處理的工作,可以通過新增一個線程來達到異步的目的。這也就是JAVA中的多線程技術。

B、最後李四寫好的材料必須交給張三,以做他用。這就是回調。

 

回調你可以這樣來理解:

A發送消息給B,B處理好A要求的事情後,將結果返回給A,A再對B返回的結果來做進一步的處理。

 

四、 Java代碼的實現

A、 回調的實現

 

Java代碼  收藏代碼
  1. /** 
  2.  * 回調接口 
  3.  * @author KOOK 
  4.  * 
  5.  */  
  6. public interface CallBack {  
  7.     /** 
  8.      * 執行回調方法 
  9.      * @param objects   將處理後的結果作爲參數返回給回調方法 
  10.      */  
  11.     public void execute(Object... objects );  
  12. }  

 

Java是面向對象的語言,因此回調函數就變成了回調接口。

 

B、 消息的發送者

 

Java代碼  收藏代碼
  1. /** 
  2.  * 簡單本地發送異步消息的類 
  3.  * @author KOOK 
  4.  * 
  5.  */  
  6. public class Local implements CallBack,Runnable{  
  7.       
  8.     /** 
  9.      * 遠程接收消息的類,模擬point-to-point 
  10.      */  
  11.     private Remote remote;  
  12.       
  13.     /** 
  14.      * 發送出去的消息 
  15.      */  
  16.     private String message;  
  17.       
  18.     public Local(Remote remote, String message) {  
  19.         super();  
  20.         this.remote = remote;  
  21.         this.message = message;  
  22.     }  
  23.   
  24.     /** 
  25.      * 發送消息 
  26.      */  
  27.     public void sendMessage()  
  28.     {  
  29.         /**當前線程的名稱**/  
  30.         System.out.println(Thread.currentThread().getName());  
  31.         /**創建一個新的線程發送消息**/  
  32.         Thread thread = new Thread(this);  
  33.         thread.start();  
  34.         /**當前線程繼續執行**/  
  35.         System.out.println("Message has been sent by Local~!");  
  36.     }  
  37.   
  38.     /** 
  39.      * 發送消息後的回調函數 
  40.      */  
  41.     public void execute(Object... objects ) {  
  42.         /**打印返回的消息**/  
  43.         System.out.println(objects[0]);  
  44.         /**打印發送消息的線程名稱**/  
  45.         System.out.println(Thread.currentThread().getName());  
  46.         /**中斷髮送消息的線程**/  
  47.         Thread.interrupted();  
  48.     }  
  49.       
  50.     public static void main(String[] args)  
  51.     {  
  52.         Local local = new Local(new Remote(),"Hello");  
  53.           
  54.         local.sendMessage();  
  55.     }  
  56.   
  57.     public void run() {  
  58.         remote.executeMessage(message, this);  
  59.           
  60.     }  
  61. }  

 

 

C、 遠程消息的接收者

Java代碼  收藏代碼
  1. /** 
  2.  * 處理消息的遠程類 
  3.  * @author KOOK 
  4.  * 
  5.  */  
  6. public class Remote {  
  7.   
  8.     /** 
  9.      * 處理消息 
  10.      * @param msg   接收的消息 
  11.      * @param callBack  回調函數處理類 
  12.      */  
  13.     public void executeMessage(String msg,CallBack callBack)  
  14.     {  
  15.         /**模擬遠程類正在處理其他事情,可能需要花費許多時間**/  
  16.         for(int i=0;i<1000000000;i++)  
  17.         {  
  18.               
  19.         }  
  20.         /**處理完其他事情,現在來處理消息**/  
  21.         System.out.println(msg);  
  22.         System.out.println("I hava executed the message by Local");  
  23.         /**執行回調**/  
  24.         callBack.execute(new String[]{"Nice to meet you~!"});  
  25.     }  
  26.       
  27. }  

 

 

 

 

執行Local類的main方法。

 

注意Local類中紅色背景的那行:

remote.executeMessage(message, this);

executeMessage方法需要接收一個message參數,表示發送出去的消息,而CallBack參數是他自己,也就是這裏的this。表示發送消息後,由Local類自己來處理,調用自身的execute方法來處理消息結果。

如果這裏不是用this,而是用其他的CallBack接口的實現類的話,那就不能稱之爲“回調”了,在OO的世界裏,那就屬於“委派”。也就是說,“回調”必須是消息的發送者來處理消息結果,否則不能稱之爲回調。這個概念必須明確。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章