Let’s start with a real-life scenario: You have a technical problem (e.g., how much is 1+1? It’s too hard! Daniel says he is busy now and will tell you the result later.

At this point, you may go to the moments, wait for Daniel to finish busy, tell you the answer is 2.

The process of asking for a problem (calling the other interface) and then telling you when the problem is resolved (calling you when it’s done, notifying you of the result) is a callback.

Classification of system calls

Call between application system modules, usually divided into: synchronous call, asynchronous call, callback.

Synchronous invocation is the most basic invocation. The A () method of class A calls the B () method of class B, and the method of class A waits until the method of class B completes execution. If B’s method blocks for an extended period of time, class A methods cannot execute properly.

If A calls B and B takes A long time to execute, asynchronous processing should be considered so that B’s execution does not affect A. Typically, A new thread is created in A to call B, and the code in A continues to execute.

Asynchrony is usually divided into two cases: first, there is no need to call the result, directly called, such as sending a message notification; Second, you need asynchronous call results, which can be implemented in Java using Future+Callable.

From the figure above we can see that back is a two-way call. The basic idea of A callback is that A calls B, and then B calls the callback method provided by A (usually callbakc()) to notify B of the result.

Callbacks are classified into synchronous callbacks and asynchronous callbacks. Most callbacks on the network are synchronous callbacks.

The synchronous callback is similar to the synchronous call. When the code runs to a certain location, if it encounters the code that needs to be called back, it waits for the callback result to return before continuing to execute.

An asynchronous callback is similar to an asynchronous call in that the code does not stop when it reaches the code that needs to be called back. Instead, it continues executing, perhaps with the result of the callback coming back later.

Synchronize the callback instance

Let’s take a synchronous callback as an example to illustrate the Java code implementation of the callback. The whole process mimics the scenario above.

First, define an interface for a CallBack to separate the CallBack function:

public interface CallBack {
    void callback(String string);
}
Copy the code

The CallBack interface provides a CallBack method that is called when the CallBack is called.

Then define the Person who asked the question:

public class Person implements CallBack { private Genius genius; public Person(Genius genius) { this.genius = genius; } @override public void callback(String String) {system.out.println (" received answer: "+ String); } public void ask() { genius.answer(this); }}Copy the code

Since Person provides CallBack methods, we implement the CallBack interface and its methods, which are mainly used to process CallBack results.

Also, because Person calls the method that corresponds to Genius, you hold a reference to Genius, which is passed in through the constructor.

Define the Genius class for answering questions:

Public class Genius {public void answer(CallBack CallBack) {system.out.println (" busy doing something else..." ); try { Thread.sleep(2000); System.out.println(" start counting...") ); } catch (InterruptedException e) { e.printStackTrace(); } system.out.println (" 2"); // callBack tells you callBack. CallBack ("2"); }}Copy the code

This simulation is busy, the thread sleep 2 seconds, after busy, start to help calculate the answer, get the answer, CallBack interface CallBack method CallBack, notify the result.

Test using the Main method:

public static void main(String[] args) {
    Genius genius = new Genius();
    Person you = new Person(genius);
    you.ask();
}
Copy the code

The output is as follows:

In the middle of something else... After everything else, start counting... The genius calculated the answer as: 2 received the answer: 2Copy the code

The above procedure implements a synchronous callback function. Of course, programmatically, Person and Genius can be abstracted further, rendered in the form of interfaces.

In the code implementation of the callback mechanism described above, the core is passing the this parameter, the caller itself, when calling the Answer method.

In essence, callback is an idea, is a mechanism, as for the specific implementation, how to code callback elegant implementation, implementation of high scalability, need to have their own genius.

Asynchronous callback instance

The above example demonstrates the synchronous callback, which is obviously affected by the Genius execution time, and requires Genius to finish processing before subsequent code in the Person method can proceed.

To improve on the example above, Person provides a method that supports asynchronous callbacks:

Public void askASyn() {system.out.println (" create thread ask questions "); new Thread(() -> genius.answer(this)).start(); System.out.println(" New thread started... ); }Copy the code

Within this method, a new thread is created to handle the Genius#answer method call, so that we can skip the Genius#answer method blocking and directly perform the following operation (log printing).

Change the method called to askASyn in the main method and print the following:

Create new thread Ask questions New thread started... In the middle of something else... After everything else, start counting... The genius calculated the answer as: 2 received the answer: 2Copy the code

New thread started… To print the information received by the callback method when processing logs and callbacks in the Genius# Answer method method.

Future-based semi-asynchrony

In addition to synchronous and asynchronous processing described above, there is a future-based semi-asynchronous processing between synchronous and asynchronous processing.

After Java uses NIO, it cannot get the real data immediately. Instead, it first gets a “Future”, which can be understood as the postmark or the express receipt. In order to get the real data, we need to constantly check whether the express has been delivered by the express receipt number “Future”.

Futures is an abstract concept that represents a value at some point that will become available. A Future either gets the result of the calculation, or an exception if the calculation fails.

When do you usually use a Future? In general, when performing a time-consuming task, using a Future allows the thread to temporarily work on other tasks, and then return the result of the equal-length task.

Scenarios where Future is often used include: 1. Computation-intensive scenarios. 2. Handle large amounts of data. 3. Remote method calls, etc.

Java comes with the Future interface in the java.util.concurrent package, which is executed asynchronously using Executor.

For example, the following code, each time a Runnable object is passed to the executorService.submit () method, the Future of the callback is checked for execution, which can be done by synchronizing the wait line processing results.

Public class TestFuture {public static void main(String[] args) {Callable<User> c = () -> { Thread.sleep(1000); thread.sleep (1000); Return new User(" zhang SAN "); }; ExecutorService es = Executors.newFixedThreadPool(2); Future<User> fn = es.submit(c); / / must call this method, otherwise the executorService. IsTerminated () to true es. Never shutdown (); IsDone returns true while (! Fn.isdone ()) {try {User nt = fn.get(); System.out.println(nt.name); } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } } } static class User { private String name; private User(String name) { this.name = name; }}}Copy the code

In this case, a new thread is created to process, but you still need to wait for the result of the processing. The advantage is that batch processing can be divided into several threads for processing at the same time, and finally the results are combined to achieve the purpose of improving processing efficiency.

summary

After this article, we must have some understanding of the Java callback mechanism, in various open source frameworks, in fact, will often see the use of callback, live learn to use.

Two classic Examples to Help you Understand the Java Callback Mechanism once and for all


Program new horizon

\

The public account “program new vision”, a platform for simultaneous improvement of soft power and hard technology, provides massive information

\