java回調函數機制

1、 概述 java

軟件模塊之間老是存在着必定的接口,從調用方式上,能夠把他們分爲三類:同步調用、回調、異步調用 編程

同步調用:一種阻塞式調用,調用方要等待對方執行完畢才返回,它是一種單向調用; 異步

回調:一種雙向調用模式,也就是說,被調用方在接口被調用時也會調用對方的接口; ide

異步調用:一種相似消息或事件的機制,解決了同步阻塞的問題,它的調用方向恰好相反,接口的服務在收到某種訊息或發生某種事件時,會主動通知客戶方(即調用客戶方的接口)。 函數




回調和異步調用的關係很是緊密:使用回調來實現異步消息的註冊,經過異步調用來實現消息的通知。
測試


理解異步和同步 this



1.通俗說,異步就是不須要等當前執行的動做完成,就能夠繼續執行後面的動做。 spa

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


案例: 線程

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

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

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


說明:

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

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


2、 異步的實現

傳統的程序執行代碼都是從上到下,一條一條執行。但生活中有不少狀況並非這樣,以上的案例中,若是李四須要幾個小時之後才能幫張三寫好材料的話,那張三就必須等幾個小時,這樣張三可能會崩潰或者抓狂。這種一條龍似的處理,顯示不太合理。


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

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

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

3、 計算機語言的實現

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

A、之前由一個線程來處理的工做,能夠經過新增一個線程來達到異步的目的。

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

回調你能夠這樣來理解:

A發送消息給B,

B處理好A要求的事情後,將結果返回給A,

A再對B返回的結果來作進一步的處理。

4、 模擬異步消息的發送與回調

A、 回調的實現


[java] view plaincopyprint?

  1. /**

  2. * 回調接口

  3. */    

  4. public interface CallBack {    

  5.    /**

  6.     * 執行回調方法

  7.     * @param objects   將處理後的結果做爲參數返回給回調方法

  8.     */    

  9.    public void execute(Object... objects );    

  10. }    


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



B、 消息的發送者

[java] view plaincopyprint?

  1. /**

  2. * 簡單本地發送異步消息的類

  3. */    

  4. public class Local implements CallBack,Runnable{    

  5.        


  6.    /**

  7.     * 遠程接收消息的類,模擬point-to-point

  8.     */    

  9.    private Remote remote;    

  10.        


  11.    /**

  12.     * 發送出去的消息

  13.     */    

  14.    private String message;    

  15.        


  16.    public Local(Remote remote, String message) {    

  17.        super();    

  18.        this.remote = remote;    

  19.        this.message = message;    

  20.    }    

  21.    


  22.    /**

  23.     * 發送消息

  24.     */    

  25.    public void sendMessage()    

  26.    {    

  27.        /**當前線程的名稱**/    

  28.        System.out.println(Thread.currentThread().getName());    

  29.        /**建立一個新的線程發送消息**/    

  30.        Thread thread = new Thread(this);    

  31.        thread.start();    

  32.        /**當前線程繼續執行**/    

  33.        System.out.println("Message has been sent by Local~!");    

  34.    }    

  35.    


  36.    /**

  37.     * 發送消息後的回調函數

  38.     */    

  39.    public void execute(Object... objects ) {    

  40.        /**打印返回的消息**/    

  41.        System.out.println(objects[0]);    

  42.        /**打印發送消息的線程名稱**/    

  43.        System.out.println(Thread.currentThread().getName());    

  44.        /**中斷髮送消息的線程**/    

  45.        Thread.interrupted();    

  46.    }    

  47.        


  48.    public static void main(String[] args)    

  49.    {    

  50.        Local local = new Local(new Remote(),"Hello");    

  51.            


  52.        local.sendMessage();    

  53.    }    

  54.    


  55.    public void run() {    

  56.        remote.executeMessage(message, this);    

  57.            


  58.    }    

  59. }    


C、 遠程消息的接收者



[java] view plaincopyprint?

  1. /**

  2. * 處理消息的遠程類

  3. *

  4. */    

  5. public class Remote {    

  6.    


  7.    /**

  8.     * 處理消息

  9.     * @param msg   接收的消息

  10.     * @param callBack  回調函數處理類

  11.     */    

  12.    public void executeMessage(String msg,CallBack callBack)    

  13.    {    

  14.        /**模擬遠程類正在處理其餘事情,可能須要花費許多時間**/    

  15.        for(int i=0;i<1000000000;i++)    

  16.        {    

  17.                


  18.        }    

  19.        /**處理完其餘事情,如今來處理消息**/    

  20.        System.out.println(msg);    

  21.        System.out.println("I hava executed the message by Local");    

  22.        /**執行回調**/    

  23.        callBack.execute(new String[]{"Nice to meet you~!"});    

  24.    }    

  25.        


  26. }    


執行 Local 類的 main 方法。

注意Local類中:


remote.executeMessage(message, this);

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

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



5、更多異步 + 回調 編程模式的例子


1.某天,我打電話向你請教問題,固然是個難題,你一時想不出解決方法,我又不能拿着電話在那裏傻等,因而咱們約定:等你想
出辦法後打手機通知我,這樣,我就掛掉電話辦其它事情去了。過了XX分鐘,個人手機響了,你興高采烈的說問題已經搞定,應該如此這般處理。故事到此結束。其中,你後來打手機告訴我結果即是一個「回調」過程;個人手機號碼必須在之前告訴你,這即是註冊回調函數;個人手機號碼應該有效而且手機可以接收到你的呼叫,這是回調函數必須符合接口規範


2.有一位老闆很忙,他沒有時間盯着員工幹活,而後他告訴本身的僱員,幹完當前這些事情後,告訴他幹活的結果。

建立一個回調接口,讓老闆得告知幹完活如何找到他的方式:留下老闆辦公室地址:


[java] view plaincopyprint?

  1. package net.easyway.test;    

  2.    


  3. /**

  4. * 此接口爲聯繫的方式,不管是電話號碼仍是聯繫地址,做爲

  5. * 老闆都必需要實現此接口

  6. *

  7. */    

  8. public interface CallBackInterface {    

  9.    


  10.    public void execute();    

  11. }  


建立回調對象,就是老闆本人,由於員工幹完活後要給他打電話,所以老闆必須實現回調接口,否則員工去哪裏找老闆?





[java] view plaincopyprint?

  1. package net.easyway.test;    

  2.    


  3. /**

  4. * 老闆是做爲上層應用身份出現的,下層應用(員工)是不知道

  5. * 有哪些方法,所以他想被下層應用(員工)調用必須實現此接口

  6. *

  7. */    

  8. public class Boss implements CallBackInterface {    

  9.        


  10.    @Override    

  11.    public void execute() {    

  12.        System.out.println("收到了!!" + System.currentTimeMillis());    

  13.            


  14.    }    

  15. }  


建立控制類,也就是員工對象,他必須持有老闆的地址(回調接口),即便老闆換了一茬又一茬,辦公室不變,總能找到對應的老闆。





[java] view plaincopyprint?

  1. package net.easyway.test;    

  2.    


  3. /**

  4. * 員工類,必需要記住,這是一個底層類,底層是不瞭解上層服務的

  5. *

  6. */    

  7. public class Employee {    

  8.    


  9.    private CallBackInterface callBack = null;    

  10.        


  11.    //告訴老闆的聯繫方式,也就是註冊    

  12.    public void setCallBack(CallBackInterface callBack){    

  13.        this.callBack = callBack;    

  14.    }    

  15.        


  16.    //工人幹活    

  17.    public void doSome(){    

  18.        //1.開始幹活了    

  19.        for(int i=0;i<10;i++){    

  20.            System.out.println("第【" + i + "】事情幹完了!");    

  21.        }    

  22.            


  23.        //2.告訴老闆幹完了    

  24.        callBack.execute();    

  25.    }    

  26. }  




測試類:


[java] view plaincopyprint?

  1. package net.easyway.test;    

  2.    


  3. public class Client {    

  4.    


  5.    public static void main(String[] args) {    

  6.            


  7.            


  8.        Employee emp = new Employee();    

  9.            


  10.        //將回調對象(上層對象)傳入,註冊    

  11.        emp.setCallBack(new Boss());    

  12.            


  13.        //開啓控制器對象運行    

  14.        emp.doSome();    

  15.    }    

  16.    


  17. }  

相關文章
相關標籤/搜索