1. 程式人生 > >Java 回撥機制解析(同步回撥/非同步回撥)

Java 回撥機制解析(同步回撥/非同步回撥)

回撥:簡單來說,就是我呼叫你的函式,你呼叫我的函式。正規一點的說法就是類A的a()函式呼叫類B的b()函式,當類B的b()函式的執行時又去呼叫類A裡的函式。是一種雙向的呼叫方式。一般情況下,回撥分兩種,分別是同步回撥非同步回撥

  • 同步回撥:一種雙向呼叫模式,被呼叫方在函式被呼叫時也會呼叫對方的函式。下面用一個計算器的例子來展示(為了方便,寫在一個檔案裡)。
public class CallBack
{
     public static void main(String []args)
     {
        int a = 10452;
        int b = 423
; //例項化計算器Calculator類 Calculator calculator = new Calculator(a,b); //呼叫計算器calculator的計算函式 calculator.calculation(); //控制檯輸出 System.out.println("/========================/"); } } //回撥介面 interface CallBackInterface { //計算的結果回撥函式 public void calculationResult
(int a, int b, int result); } //計算的具體邏輯類 class Logic { //計算的具體邏輯(計算方式) public void calculationLogic(int a, int b, CallBackInterface callBackInterface) { int result = a + b; //利用傳進來的物件,回撥計算結果. callBackInterface.calculationResult(a, b, result); } } //計算器類,實現了回撥介面,用於本類的例項化物件傳值
class Calculator implements CallBackInterface { private int a,b; public Calculator(int a, int b) { this.a = a; this.b = b; } public void calculation() { /*匿名例項化計算的具體邏輯類Logic,並呼叫計算函式. this是本類物件,因為實現了回撥介面CallBackInterface,所以可以傳值.*/ new Logic().calculationLogic(a, b, this); } //因為實現了回撥介面CallBackInterface,必須要重寫計算的結果回撥函式calculationResult public void calculationResult(int a, int b, int result) { //控制檯輸出 System.out.println(a + " + " + b + " = " + result); } }

執行結果:
10452 + 423 = 10875
/========================/

  • 非同步回撥:一種類似訊息或事件的機制,被呼叫方在函式在收到某種訊息或發生某種事件時,才去呼叫對方的函式,即通過非同步訊息進行通知。簡單來說,類A的a()函式呼叫類B的b()函式,但是b()函式很耗時,不確定什麼時候執行完畢,如果是同步呼叫的話會等b()執行完成後才往下執行回撥類A中的函式,如果是非同步回撥的話呼叫了b()函式,雖然b()函式沒有執行完,但仍然繼續往下執行,為了完成這點,就需要另開一個執行緒了。下面還是用一個計算器的例子來展示(為了方便,寫在一個檔案裡)。
public class CallBack
{
     public static void main(String []args)
     {
        int a = 10452;
        int b = 423;
        //例項化計算器Calculator類
        Calculator calculator = new Calculator(a,b);
        //呼叫計算器calculator的計算函式
        calculator.calculation();
        //控制檯輸出
        System.out.println("/========================/");
     }
}

//回撥介面
interface CallBackInterface
{
    //計算的結果回撥函式
     public void calculationResult(int a, int b, int result);
}

//計算的具體邏輯類
class Logic
{
    //計算的具體邏輯(計算方式)
    public void calculationLogic(int a, int b, CallBackInterface callBackInterface)
    {
        int result = a + b;
        //讓執行緒等待5秒
        try
        { 
            Thread.sleep(5 * 1000); 
        } catch (InterruptedException e)
        { 
            e.printStackTrace(); 
        } 
        //利用傳進來的物件,回撥計算結果.
        callBackInterface.calculationResult(a, b, result);
    }
}

//計算器類,實現了回撥介面,用於本類的例項化物件傳值
class Calculator implements CallBackInterface
{
    private int a,b;

    public Calculator(int a, int b)
    {
        this.a = a;
        this.b = b;
    }

    public void calculation()
    {
        //開啟另一個子執行緒
        new Thread(new Runnable()
        { 
            public void run()
            { 
                /*匿名例項化計算的具體邏輯類Logic,並呼叫計算函式.
                this是本類物件,因為實現了回撥介面CallBackInterface,所以可以傳值.*/
                new Logic().calculationLogic(a, b, Calculator.this);
            } 
        }).start(); 
    }

    //因為實現了回撥介面CallBackInterface,必須要重寫計算的結果回撥函式calculationResult
    public void calculationResult(int a, int b, int result)
    {
        //控制檯輸出
        System.out.println(a + " + " + b + " = " + result);
    }
}

執行結果:
/========================/
10452 + 423 = 10875

你會發現,輸出”/====/”明明是放在程式碼的最後執行的,結果卻先執行輸出了,這是因為開了另一個執行緒,而非同步回撥和同步回撥最大的不同就是非同步回撥裡新建了一個子執行緒。非同步回撥常見於請求伺服器資料,當取到資料時,會進行回撥。

擴充套件知識:另一種回撥(同步),主要是為解決當實現的邏輯不明確時的問題。還是用計算器的例子,比如不一定用計算器進行加法運算,也有可能進行乘法運算(為了方便,寫在一個檔案裡)。

public class CallBack
{
     public static void main(String []args)
     {
        int aa = 10452;
        int bb = 423;
        //例項化計算器Calculator類,並傳一個Logic物件
        Calculator calculator = new Calculator(new Logic()
        {
            //重寫計算邏輯函式calculationLogic,實現具體計算邏輯
            public void calculationLogic(int a, int b){
                int result = a * b;
                System.out.println(a + " * " + b + " = " + result);
            }
        });
        //呼叫計算器calculator的計算函式calculation
        calculator.calculation(aa, bb);
        //控制檯輸出
        System.out.println("/========================/");
     }
}

//計算的邏輯回撥介面
interface Logic
{
    //計算的邏輯回撥函式
     public void calculationLogic(int a, int b);
}

//計算器類
class Calculator
{
    private Logic logic;

    public Calculator(Logic logic)
    {
        this.logic = logic;
    }

    public void calculation(int aa, int bb)
    {
        //呼叫logic物件裡的計算邏輯函式calculationLogic
        logic.calculationLogic(aa, bb);
    }
}

執行結果:
10452 * 423 = 4421196
/========================/

非同步回撥也同理,在Calculator類的calculation()函式裡新建一個執行緒就行了,這裡就不舉例了。