Welcome to Java Learning: Decoding Callbacks in Java

directory

  • Calls between modules

  • “Callback” in multithreading

  • Java callback mechanism in action

    • Example 1: Synchronous invocation

      • 1.1 Synchronous call code
  • Example 2: From the shallow to the deep

  • Example 3: Tom does the exercises

  • Refer to the article


Calls between modules

This section from www.cnblogs.com/xrq730/p/64…

In an application system, no matter what language is used for development, there must be calls between modules, which can be divided into several ways:

(1) Synchronous call

Synchronous invocation is the most basic and simplest invocation method. Method A () of class A calls method B () of class B, waiting for method B () to complete, and for method A () to continue down. This method is used when method B () does not take long to execute, because if method B () takes long to execute or blocks directly, the rest of the code in method A () cannot execute, thus blocking the whole process.

(2) Asynchronous call

Asynchronous invocation is a method of invocation to solve the problem that synchronous invocation may block and cause the whole process to get stuck. Method A () of class A calls method B () of class B with A fresh thread, and the code is then executed directly down, so that method A () does not block execution of method A () no matter how long method B () takes.

But this way, because the method (a) don’t wait for method b () completes, the method a () need to b () under the condition of the execution result (depending on the specific business, some business such as asynchronous thread send a WeChat notification, refresh a cache this is unnecessary), must pass through a certain way to analysis the execution result b () to monitor.

In Java, you can do this using Future+Callable, as described in my article Java Multithreading 21: CyclicBarrier, Callable, Future, and FutureTask for Other Components in Multithreading.

(3) Callback

1. What is a callback? Generally speaking, there is a certain call relationship between modules, which can be divided into three types of synchronous call, asynchronous call and callback. Synchronous call is A blocking call, that is, function A is called by writing function B’s function name in the function body, so that the corresponding function B’s code in memory can be executed. Asynchronous invocation is A message or event-like mechanism that solves the problem of synchronous blocking. For example, after A notifies B, they go their separate ways without affecting each other. Unlike synchronous invocation, after A notifies B, A cannot continue to go until B finishes. Callback is A two-way invocation mode. That is, the invoked interface also invokes the interface of the other side when invoked. For example, A calls B, and B calls A again after execution.

Callbacks are commonly used for coordination between layers. The upper layer installs its function on the lower layer, which is called a callback, and the lower layer triggers a callback under certain conditions. For example, as a driver, is a bottom layer. When it receives a data, it will not only complete the processing work of this layer, but also carry out a callback and hand the data to the upper application layer for further processing. This is common in hierarchical data communication.

“Callback” in multithreading

In Java multithreading, a combination of Callable and Future or FutureTask can be used to retrieve the return value of the thread after execution. This is done by calling callable’s Call method via get to get the return value.

In fact, this method is not a callback in nature, the callback requires that after the task is completed, the caller actively calls back to the caller’s interface. Here, the caller actively blocks to get the return value using the GET method.

public classA callback in multithreading{
    // We simply use future and callable to implement the thread after execution
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ExecutorService executor = Executors.newCachedThreadPool();
        Future<String> future = executor.submit(new Callable<String>() {
            @Override
            public String call(a) throws Exception {
                System.out.println("call");
                TimeUnit.SECONDS.sleep(1);
                return "str"; }});// Manually block the call to get the return value from the call method.
        System.out.println(future.get());
        // It needs to be closed manually, otherwise the thread in the thread pool will continue to execute.
        executor.shutdown();

    // Use FutureTask as both thread execution unit and data request unit.
    FutureTask<Integer> futureTask = new FutureTask(new Callable<Integer>() {
        @Override
        public Integer call(a) throws Exception {
            System.out.println("dasds");
            return newRandom().nextInt(); }});new Thread(futureTask).start();
    // block to get the return value
    System.out.println(futureTask.get());
}
@Test
public void test (a) {
    Callable callable = new Callable() {
        @Override
        public Object call(a) throws Exception {
            return null; }}; FutureTask futureTask =newFutureTask(callable); }}Copy the code

Java callback mechanism in action

I’ve heard of the callback mechanism once in a while and vaguely understood it, but when I was forced to write a simple example program, I was blindfolded. As I get more experience and hear callbacks here and there, it’s time to take a closer look at the Java callback mechanism. There are a lot of articles on The web about Java callbacks, but it’s always confusing and confusing to read, especially when you see someone else’s code taking two steps. So I decided to write an article about the Java mechanism to facilitate everyone and myself to learn more about the Java callback mechanism.

First, what is a callback function? A callback function is a function called through a function pointer. If you pass a pointer (address) to a function as an argument to another function, we say it is a callback function when the pointer is used to call the function to which it points. The callback function is not called directly by the implementation of the function, but is called by another party when a particular event or condition occurs in response to that event or condition [2].

Sorry, I have read the above explanation several times, but I do not understand the profound mystery, I believe some readers you are the same. Light said not practice false handle, we still understand the context in actual combat.

Example 1: Synchronous invocation

This article takes BottomService and UpperService as examples to invoke bottom-layer services using the upper-layer services. The overall execution process is as follows:

The first step: perform UpperService callBottomService ();

Step 2: Execute bottomservice.bottom ();

Step 3: perform UpperService. UpperTaskAfterCallBottomService ()

1.1 Synchronous call code

Synchronously invoke sequence diagrams

1.1.1 BottomService class: bottomservice.java


package synchronization.demo;

/** * Created by lance on 2017/1/19. */

public class BottomService {

public String bottom(String param) {

try { // Simulate the underlying processing time, the upper layer services need to wait

Thread.sleep(3000);

} catch (InterruptedException e) {

e.printStackTrace();

}

return param +" BottomService.bottom() execute -->"; }}Copy the code

1.1.2 Upper Layer Service Interface: upperservice.java

package synchronization.demo;

/** * Created by lance on 2017/1/19. */

public interface UpperService {

public void upperTaskAfterCallBottomService(String upperParam);

public String callBottomService(final String param);

}
Copy the code

1.1.3 Upper-layer service interface implementation class: upperServiceImp.java

package synchronization.demo;

/** * Created by lance on 2017/1/19. */

public class UpperServiceImpl implements UpperService {

private BottomService bottomService;

@Override

public void upperTaskAfterCallBottomService(String upperParam) {

System.out.println(upperParam + " upperTaskAfterCallBottomService() execute.");

}

public UpperServiceImpl(BottomService bottomService) {

this.bottomService = bottomService;

}

@Override

public String callBottomService(final String param) {

return bottomService.bottom(param + " callBottomService.bottom() execute --> "); }}Copy the code

1.1.4 Test Test class: test.java

package synchronization.demo;

import java.util.Date;

/** * Created by lance on 2017/1/19. */

public class Test {

public static void main(String[] args) {

BottomService bottomService = new BottomService();

UpperService upperService = new UpperServiceImpl(bottomService);

System.out.println("=============== callBottomService start ==================:" + new Date());

String result = upperService.callBottomService("callBottomService start --> ");

/ / upperTaskAfterCallBottomService execution must wait callBottomService () call BottomService. The bottom after () method returns to perform

upperService.upperTaskAfterCallBottomService(result);

System.out.println("=============== callBottomService end ====================:" + newDate()); }}Copy the code

1.1.5 Output Results:

=============== callBottomService start ==================:Thu Jan 19 14:59:58 CST 2017

callBottomService start -->  callBottomService.bottom() execute -->  BottomService.bottom() execute --> upperTaskAfterCallBottomService() execute.

=============== callBottomService end ====================:Thu Jan 19 15:00:01 CST 2017
Copy the code

Note the output:

In synchronous mode, Test calls callBottomService() until the execution is complete, and then performs the next step, that is, the execution is complete. The callBottomService starts at Thu Jan 19 14:59:58 CST 2017, and ends at Thu Jan 19 15:00:01 CST 2017, which takes 3 seconds, the same time as the simulation time, that is, 3000 milliseconds.

Example 2: From the shallow to the deep

A few days ago, the company asked a question about Java callback in the interview, because there is not much research on this aspect, so the answer was vague, this time I specially come to make up for it. Look at the callback explanation and examples on the Internet, are so around the mouth, take a long time to see around back, in fact, callback is a very simple mechanism. Let’s say we have two classes, A and B, and in A we have A method A () and in B we have A method B (). A calls method B () from B, and A () from method B () from method A, thus realizing the functions of both B () and A ().

Confused: why so much trouble, I just call A () method in the class A B.b() method. Answer: callback is more like a convention, is if I call the b () method, then it must be a callback, without the need to show to invoke a callback, Java – shallow We use examples to explain: xiao Ming and xiao li went to have breakfast together, but xiao li got up a little late to wash first, such as xiao li wash gargle finished, inform xiao Ming to go to dinner. Xiao Ming is class A and Xiao Li is class B. The event of going to dinner together is method A (), and Xiao Li washing up is method B ().

public class XiaoMing { 
   // Xiao Ming and Xiao Li have dinner together
   public void eatFood(a) {
      XiaoLi xl = new XiaoLi();
      //A calls B's method
      xl.washFace();
   }
 
   public void eat(a) {
      System.out.print("Xiao Ming and Xiao Li go to eat lobster."); }} So how to let Xiao Li wash after informing Xiao Ming to have a meal togetherpublic class XiaoMing { 
   // Xiao Ming and Xiao Li have dinner together
   public void eatFood(a) {
      XiaoLi xl = new XiaoLi();
      //A calls B's method
      xl.washFace();
      eat();
   }
 
   public void eat(a) {
      System.out.print("Xiao Ming and Xiao Li go to eat lobster."); }}Copy the code

But having said that this is not a callback function, it can’t do this. The correct way to do this is as follows

public class XiaoLi{/ / xiao li
   public void washFace(a) {
    System.out.print("Xiao Li needs to wash.");
    XiaoMing xm = new XiaoMing();
        //B calls A's method
    xm.eat();// After washing, let's go to dinner}}Copy the code

This can achieve washFace() and eat() at the same time. After Xiao Li washed, and then inform Xiao Ming to have a meal together, this is the callback.

Two, Java callback – but careful partners may find that Xiao Li’s code is completely written dead, this kind of occasion may be applicable to go to dinner with Xiao Ming, but if Xiao Li washed and did not eat, want to go to the Internet with Xiao Wang, this way is not applicable. In fact, the above is pseudo code, just to help you understand, the real situation is to use the interface to set the callback. Now let’s continue to use the example of Xiao Ming and Xiao Li going to dinner to show how the interface is used.

Xiao Ming and Xiao Li made an appointment to have breakfast together, but Xiao Li got up a little late to wash first, and so xiao Li finished washing, inform Xiao Ming to eat together again. Xiao Ming is class A and Xiao Li is class B. The difference is that we create a new interface for eating, EatRice, with an abstract method called eat(). Call this interface in the text and implement eat(); Lee declares the interface object and calls the abstract method of the interface. It’s a little tricky here, but that’s okay, because if you look at the example, it’s clear.

EatRice interface:

public interface EatRice {
   public void eat(String food); } xiao Ming:public class XiaoMing implements EatRice{/ / xiao Ming
    
   // Xiao Ming and Xiao Li have dinner together
   public void eatFood(a) {
    XiaoLi xl = new XiaoLi();
    //A calls B's method
    xl.washFace("Lobster".this);// This refers to the EatRice interface implemented by xiaoming
   }
 
   @Override
   public void eat(String food) {
    // TODO Auto-generated method stub
    System.out.println("Xiao Ming and Xiao Li go to eat together."+ food); }} Xiao Li:public class XiaoLi{/ / xiao li
   public void washFace(String food,EatRice er) {
    System.out.println("Xiao Li needs to wash.");
        //B calls A's methoder.eat(food); }} Test Demo:public class demo {
   public static void main(String args[]) {
    XiaoMing xm = newXiaoMing(); xm.eatFood(); }}Copy the code

Test results:

This implements soft coding in the form of interfaces. Through the form of interface, I can realize that after Xiao Li washes, xiao Wang and Xiao Li go to the Internet together. The following code

public class XiaoWang implements EatRice{/ / wang
    
   Xiao Wang and Xiao Li go to the Internet together
   public void eatFood(a) {
    XiaoLi xl = new XiaoLi();
    //A calls B's method
    xl.washFace("Dance to the Internet".this);
   }
 
   @Override
   public void eat(String bar) {
    // TODO Auto-generated method stub
    System.out.println("Xiao Wang and Xiao Li will go together."+ bar); }}Copy the code

Example 3: Tom does the exercises

The math teacher asked Tom to do a problem. The math teacher didn’t have to stare at Tom during the problem. Instead, he was playing with his cell phone.

1 The math teacher needs a quote from Tom before he can send the question to Tom.

The math teacher needs to provide a way for Tom to tell him the answer after he finishes the problem.

3 Tom needs a quote from the math teacher so that Tom can give the answer to the teacher instead of the PE teacher next door.

Callback interface, can be understood as the teacher interface

    // A callback is when A calls B to do something, and B tells A the result when B is done, in which time A can do something else.
    // There is A method in this interface, which means the method that B tells A when he has finished the problem.
    // So we must provide this interface for B to call back and forth.
    // Callback interface,
    public interface CallBack {
        void tellAnswer(int res);
    }
Copy the code

Math Teacher

    // The teacher class instantiates the callback interface, that is, after the student has written the question, the teacher provides the method for callback.
    // How can a student call a teacher's method by passing a reference to the teacher's method in the student class?
    // The teacher needs to assign students to answer the questions, so students' examples are also passed in.
public class Teacher implements CallBack{
    private Student student;

    Teacher(Student student) {
        this.student = student;
    }

    void askProblem (Student student, Teacher teacher) {
        // The main method is run by the main thread. To implement the asynchronous callback, start a thread to operate
        new Thread(new Runnable() {
            @Override
            public void run(a) {
                student.resolveProblem(teacher);
            }
        }).start();
        // After the teacher asks the students to do the exercises, you can do other things such as playing with your mobile phone while waiting for the students to answer.\
        // There is no need to wait synchronously, which is the benefit of the callback.
        // Of course you could just start a thread and let the student do the homework, but that would not let the student inform the teacher.
        // Another mechanism is needed to implement the notification process.
        // Of course, future and callable in multithreading can also implement data fetching.
        for (int i = 1; i <4; i ++) { System.out.println("The teacher played while the students answered the question." + i + "Phone of the second"); }}@Override
    public void tellAnswer(int res) {
        System.out.println("the answer is "+ res); }}Copy the code

Students interface

    // A reference to the teacher must be passed in to solve the problem, otherwise the callback to the specific instance cannot be completed.
    // The advantage of writing as an interface is that many students can implement this interface and teachers can pass it when asking questions
    // Pass List
      
        to aggregate students.
      
public interface Student {
    void resolveProblem (Teacher teacher);
}
Copy the code

Student Tom

public class Tom implements Student{

    @Override
    public void resolveProblem(Teacher teacher) {
        try {
            // After thinking for 3 seconds, the student gets the answer and tells the teacher through the callback method provided by the teacher.
            Thread.sleep(3000);
            System.out.println("work out");
            teacher.tellAnswer(111);
        } catch(InterruptedException e) { e.printStackTrace(); }}Copy the code

The test class

public class Test {
    public static void main(String[] args) {
        / / test
        Student tom = new Tom();
        Teacher lee = new Teacher(tom);
        lee.askProblem(tom, lee);
        / / the result
// The teacher played with his mobile phone for 1 second while waiting for the students to answer the questions
// The teacher played with his mobile phone for 2 seconds while waiting for the students to answer the questions
// The teacher played with his mobile phone for 3 seconds while waiting for the students to answer the questions
// work out
// the answer is 111}}Copy the code

Refer to the article

Blog.csdn.net/fengye45454… Blog.csdn.net/xiaanming/a… www.cnblogs.com/prayjourney… Blog.csdn.net/qq\_2565294… My.oschina.net/u/3703858/b…