Summary of Java callback mechanism

In an application system, no matter what language is used for development, there must be calls between modules. There are several ways to call:
1. Synchronous call


Synchronous call is the most basic and simplest way to call. Method a() of class A calls method b() of class B, waiting for the execution of method b(), and method a() continues to move forward   This calling method is applicable to the case that the execution time of method b() is not long, because if the execution time of method b() is long or directly blocked, the remaining code of method a() cannot be executed, which will block the whole process
2. Asynchronous call


Asynchronous call is A call method to solve the problem that synchronous call may block and cause the whole process to jam   Method a() of class A calls method b() of class B by starting A new thread, and then the code is directly executed downward, so that the execution of method a() will not be blocked no matter how long the execution time of method b(). However, in this way, since method a() does not wait for the execution of method b(), when method a() needs the execution result of method b() (depending on the specific business, some businesses, such as starting an asynchronous thread, sending A wechat notification and refreshing A cache, are not necessary). You must listen to the execution results of method b() in A certain way. In Java, you can do this by using Future+Callable. See the article for details Java multithreading 21: CyclicBarrier, Callable, Future and FutureTask of other components under multithreading.
3. Callback: as shown in the figure below, callback is a two-way calling method. In fact, callback can also be divided into synchronous and asynchronous. Synchronous callback is used in the explanation, and asynchronous callback is used in the second example


The idea of callback is:

  • The a() method of class A calls the b() method of class B
  • After the execution of the b() method of class B, actively call the callback() method of class A

Popularly speaking: it is called a method C in class B in class A, and then calling the method D in class A. in the B class, D is called callback method, which means that you are a little dizzy. Actually, at the beginning, I didn't understand it too. I saw people say the classic callback way:

  1. class A implements interface callback -- background 1
  2. class A contains a reference b to class B -- background 2
  3. class B has a method f(CallBack callback) with a callback parameter - background 3
  4. Object a of a calls method f of B (callback callback) -- class a calls a method C of class B
  5. Then B can call the A method in the f(CallBack callback) method B class calls a method D of class A.

Type of callback

Callbacks are divided into synchronous callbacks and asynchronous callbacks. If simulated by buying lottery tickets,   When I buy a lottery ticket, I call the lottery network and give me the returned results to determine whether I win the prize. Synchronous callback is that after I buy a lottery ticket, I need to wait for the results returned by the lottery network. At this time, I can't do anything else. I have to wait for the results, which is called synchronous callback,   Synchronization means waiting. I can't do other things. I have to wait. Asynchronous callback means that after I buy the lottery, I can do other things. Then when the lottery network has the result and message, it will return the message to me. The most obvious way is to add another method to the function that gets the lottery result. If my other methods can be executed immediately, then It's asynchronous (it takes a long time to give whether you win the prize). In the test function, the first and last two occur in the thread of the test function. They must be in order one after the other. This place is not the place where synchronous and asynchronous are displayed

Synchronous callback

Synchronous callbacks and asynchronous callbacks are mainly reflected in whether they need to wait. Synchronous calls, if the API (third-party API) of the called party takes a long time to deal with the problem, we need to wait, that is, synchronous callbacks. If we don't need to understand the results after the call, we can go after the call and do other things, that is, asynchronous calls,   Asynchronous calls need to start a new thread where we call the third-party API, while synchronous calls are no different from ordinary calls
example
OrderResult interface, where the method getOrderResult

public interface OrderResult {
    /**
     * Status of ordered goods
     *
     * @param state
     * @return
     */
    //Parameters can be used or not according to your actual needs
    public String getOrderResult(String state);
}

Store class. The store provides an interface that will return no reservation message. It calls back the method of the OrderResult interface to return the status of the reserved goods. The focus is on the returnOrderGoodsInfo(OrderResult order) method,   It reflects the callback   Store is the called party. The called party needs to call back the method of the calling party. This method is actually a method of the callback interface

public class Store {
    @Getter
    @Setter
    private String name;

    Store(String name) {
        this.name = name;
    }

    /*Callback function, pass the structure to the method we can't call directly, and then get the result*/
    public String returnOrderGoodsInfo(OrderResult order) {
        String[] s = {"Ordering...", "Subscription failed", "Upcoming shipment!", "During transportation...", "Already posted"};
        Random random = new Random();
        int temp = random.nextInt(5);
        String s1 = s[temp];
        return order.getOrderResult(s1);
    }
}

SyncBuyer class, synchronous customer class, which obtains the order status of goods. orderGoods() calls the returnOrderGoodsInfo() method of store to return the call information of goods, but in returnOrderGoodsInfo() of store class In the method, taking the OrderResult interface as the parameter and calling the OrderResult interface in turn is equivalent to calling its subclass SyncBuyer itself. Taking him as the parameter and calling the getOrderResult(String state) method, that is, the method of the OrderResult interface, is equivalent to completing a call cycle and obtaining the results we can't give ourselves
The "cycle" of this place It is the key to callback. It calls for a normal caller to provide results to the other party. It inherits a callback interface and implements it. Then it calls the API method of the third party. The third party uses the callback structure as the parameter in the method we invoke, and then calls the method in the interface, which can return the corresponding result to us. There is a method of this interface, but our own class, or this class itself, cannot call this method. It can also be said that calling this method will not produce effective results. The callback is reflected here in the returnOrderGoodsInfo(OrderResult order) method in the Store class

/*Synchronization, customers book goods in the store, and the store notifies customers of the reservation*/
public class SyncBuyer implements OrderResult {
    @Getter
    @Setter
    private Store store;//Shop
    @Getter
    @Setter
    private String buyerName;//Shopper name
    @Getter
    @Setter
    private String goodsName;//Trade name purchased

    SyncBuyer(Store store, String buyerName, String goodsName) {
        this.store = store;
        this.buyerName = buyerName;
        this.goodsName = goodsName;
    }

    /*Call to return the information of the ordered item from the store*/
    public String orderGoods() {
        String goodsState = store.returnOrderGoodsInfo(this);
        System.out.println(goodsState);
        myFeeling();// Test synchronization or asynchrony. Synchronization needs to wait, and asynchrony does not need to wait
        return goodsState;

    }

    public void myFeeling() {
        String[] s = {"A little excited", "expect!", "I hope it's a good one!"};
        Random random = new Random();
        int temp = random.nextInt(3);
        System.out.println("I am" + this.getBuyerName() + ", How I feel now: " + s[temp]);
    }

    /*We don't call the callback method ourselves. The result given by this method is given to us by other interfaces or programs, and we can't generate it ourselves*/
    @Override
    public String getOrderResult(String state) {
        return "stay" + this.getStore().getName() + "Store ordered" + this.getGoodsName() + "Toys, The current booking status is: " + state;
    }
}

Test2Callback class, which tests the results of synchronous callback,

public class Test2Callback {
    public static void main(String[] args) {
        Store wallMart = new Store("Wal Mart, SHAZHONG Road");
        SyncBuyer syncBuyer = new SyncBuyer(wallMart, "Xiao Ming", "Super Iron Fan Princess");
        System.out.println(syncBuyer.orderGoods());
    }
}

Asynchronous callback

The code level difference between synchronous callback and asynchronous callback is whether we open up a new thread for the third-party API. There is no other difference
example
OrderResult interface, where the method getOrderResult

public interface OrderResult {
    /**
     * Status of ordered goods
     *
     * @param state
     * @return
     */
    //Parameters can be used or not according to your actual needs
    public String getOrderResult(String state);
}

Store class. The store provides an interface that will return without reservation message. Call back the method of OrderResult interface to return the status of reserved goods

public class Store {
    @Getter
    @Setter
    private String name;

    Store(String name) {
        this.name = name;
    }

    /*Callback function, pass the structure to the method we can't call directly, and then get the result*/
    public String returnOrderGoodsInfo(OrderResult order) {
        String[] s = {"Ordering...", "Subscription failed", "Upcoming shipment!", "During transportation...", "Already posted"};
        Random random = new Random();
        int temp = random.nextInt(5);
        String s1 = s[temp];
        return order.getOrderResult(s1);
    }
}

NoSyncBuyer class asynchronously calls the returnOrderGoodsInfo(OrderResult order) method of Store class to return the result of commodity conversion

/*asynchronous*/
@Slf4j
public class NoSyncBuyer implements OrderResult {
    @Getter
    @Setter
    private Store store;//Shop
    @Getter
    @Setter
    private String buyerName;//Shopper name
    @Getter
    @Setter
    private String goodsName;//Trade name purchased

    NoSyncBuyer(Store store, String buyerName, String goodsName) {
        this.store = store;
        this.buyerName = buyerName;
        this.goodsName = goodsName;
    }

    /*Call to return the information of the ordered item from the store*/
    public String orderGoods() {
        String goodsState = "--";
        MyRunnable mr = new MyRunnable();
        Thread t = new Thread(mr);
        t.start();
        System.out.println(goodsState);
        goodsState = mr.getResult();// Get return value
        myFeeling();// Used to test whether asynchronous or sequential execution
        return goodsState;
    }

    public void myFeeling() {
        String[] s = {"A little excited", "expect!", "I hope it's a good one!"};
        Random random = new Random();
        int temp = random.nextInt(3);
        System.out.println("I am" + this.getBuyerName() + ", How I feel now: " + s[temp]);
    }

    /*We don't call the callback method ourselves. The result given by this method is given to us by other interfaces or programs, and we can't generate it ourselves*/
    @Override
    public String getOrderResult(String state) {
        return "stay" + this.getStore().getName() + "Store ordered" + this.getGoodsName() + "Toys, The current booking status is: " + state;
    }

    // Start another thread, but there is no return value. What's going on
    // When debugging, you can still get the value after waiting for a while, but it is not obtained immediately. When print is displayed, it is null. You need to pay attention?
    private class MyRunnable implements Runnable {
        @Getter
        @Setter
        private String result;

        @Override
        public void run() {
            try {
                Thread.sleep(10000);
                result = store.returnOrderGoodsInfo(NoSyncBuyer.this);// You cannot return a value when using an anonymous function
            } catch (InterruptedException e) {
                log.error("Something big happened, There is a problem with the asynchronous callback", e);
            }
        }
    }
}

Test2Callback class, test the results of synchronous callback and asynchronous callback

public class Test2Callback {
    public static void main(String[] args) {
        Store wallMart = new Store("Wal Mart, SHAZHONG Road");
        SyncBuyer syncBuyer = new SyncBuyer(wallMart, "Xiao Ming", "Super Iron Fan Princess");
        System.out.println(syncBuyer.orderGoods());


        System.out.println("\n");
        Store lawson = new Store("Shazhong road Rosen convenience store");
        NoSyncBuyer noSyncBuyer = new NoSyncBuyer(lawson, "cherry", "Transformers");
        System.out.println(noSyncBuyer.orderGoods());
    }
}

ref:
1.Interpretation of Java callback mechanism, 2.A classic example allows you to thoroughly understand the java callback mechanism, 3.JAVA callback mechanism (CallBack) details, 4.JAVA callback mechanism (CallBack) details, 5.Java multithreading 21: CyclicBarrier, Callable, Future and FutureTask of other components under multithreading

Keywords: Java Back-end Programmer

Added by rationalrabbit on Mon, 06 Dec 2021 23:59:32 +0200