Tamping Java Foundation Series 11: Deep Understanding of Callback Mechanisms in Java

Posted by fcaserio on Wed, 09 Oct 2019 16:37:59 +0200

Catalog

This series of articles will be sorted out into my Java Interview Guide warehouse on GitHub. For more interesting information, please visit my warehouse.

https://github.com/h2pl/Java-Tutorial

If you like, please click Star ha.

The article was first published on my personal blog:

www.how2playlife.com

This article is part of a series of articles on ramming Java Foundation Series, which is called Java technology. This part of the content comes from the Internet. In order to make the topic clear and clear, it also integrates a lot of technology blog content that I think is good, and cites some good blog articles. If there is any infringement, please contact the author.
This series of blogs will tell you how to learn basic knowledge of Java from step by step, from the entry to the advanced level, and then get to the actual combat, then understand the realization principle behind each Java knowledge point, and understand the whole Java technology system and form its own knowledge framework. In order to better summarize and test your learning results, this series of articles will also provide interview questions and reference answers corresponding to each knowledge point.

If you have any suggestions or questions about this series, you can also pay attention to the public number [Java technology]. Contact your author and welcome you to participate in the creation and revision of this series of blogs.

@

Calls between modules

This section is excerpted from https://www.cnblogs.com/xrq730/p/6424471.html.

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) Synchronized invocation

Synchronized invocation is the most basic and simplest method of invocation. Method a() of class A calls method b() of class B, and waits for method b() to finish executing. Method a() goes on. This invocation method is suitable for the case of method b() execution time is not long, because if method b() execution time is long or directly blocked, the remaining code of method a() can not be executed, which will cause blocking of the whole process.

(2) Asynchronous invocation

Asynchronous invocation is a kind of invocation method to solve the problem that synchronous invocation may block and cause the whole process to be stuck. Method method a() of Class A calls method b() of Class B through a new thread, and the code then executes directly down, so that no matter how long method b() executes, the execution of method a() will not be blocked.

But this way, because the method a() does not wait for the execution of the method b(), in the case of method a() needs the method b() to execute the result (depending on the specific business, some businesses such as the asynchronous asynchronous thread send a notification, refresh a cache, this does not have to), we must monitor the execution result of the method B (a) in a certain way.

In Java, you can use Future+Callable to do this. See my article Java Multithreading 21: Cyclic Barrier, Callable, Future and FutureTask for other components under multithreading.

(3) Callback

1, what is callback?
Generally speaking, there is a certain call relationship between modules, which can be divided into three types: synchronous call, asynchronous call and callback. Synchronized call is a blocking call, which is called in the function body of function A by writing the function name of function B, so that the code of corresponding function B in memory can be executed. Asynchronous invocation is a mechanism similar to message or event, which solves the problem of synchronous blocking. For example, after A notifies B, they go their own way without affecting each other. Instead of synchronous invocation, A notifies B and has to wait until B has finished before A continues. Callback is a two-way invocation mode, that is to say, when the invoked interface is invoked, the other side's interface will also be invoked, such as A to invoke B, B to invoke A after execution.

2. Use of callbacks
Callback is generally used for inter layer cooperation. The upper layer installs the function of this layer in the lower layer, which is called callback, and the lower layer triggers callback under certain conditions. For example, as a driver, it is a bottom layer. When he receives a data, he will not only complete the processing work of this layer, but also make a callback, which will be handed over to the upper application layer for further processing, which is very common in the layered data communication.

Callback in multithreading

In Java multithreading, the return value of thread execution can be obtained through the combination of callable and future or futuretask. The implementation method is to call the call method of callable through get method to get the return value.

In fact, this method is not callback in essence, callback requires that the callee actively calls back the caller's interface after the task is completed. This is where the caller takes the initiative to block the get method to get the return value.

public class Callback in multithreading {
    //Here we simply use future and callable to implement thread 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() throws Exception {
                System.out.println("call");
                TimeUnit.SECONDS.sleep(1);
                return "str";
            }
        });
        //The manual blocking call get gets the return value through the call method.
        System.out.println(future.get());
        //You need to close it manually, otherwise the thread in the thread pool will continue to execute.
        executor.shutdown();

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

}
}

Java callback mechanism in practice

I have heard of the callback mechanism occasionally, and I can vaguely understand some meanings. But when I write a simple example program, I am dumbfounded. With more work experience, I often hear callbacks used here and there. It's time for me to study Java callback mechanism. There are a lot of articles about Java callbacks on the Internet, but after reading them, they are always in the clouds and do not know what to do, especially when they take two steps to grab someone else's code. So I decided to write an article about Java mechanism, so that we can learn Java callback mechanism more deeply.

First, what is the callback function, which refers to the explanation of Encyclopedia: callback function is a function called by function pointer. If you pass the pointer (address) of a function as a parameter to another function, when the pointer is used to call the function to which it refers, we call it a callback function. A callback function is not called directly by the implementer of the function, but by another party when a particular event or condition occurs. It is used to respond to the event or condition [2].

Sorry, I have read the above explanations several times, and I have not understood the profound mystery. I believe some readers are also like you. Let's just say that we don't practise fake tactics, but let's understand the context in real combat.

Example 1: Synchronized invocation

Taking Bottom Service and UpperService as examples, this paper invokes the underlying service by using the upper service. The overall execution process is as follows:

Step 1: Execute UpperService.callBottomService();

Step 2: Execute BottomService.bottom();

Step 3: Execute UpperService.upperTaskAfterCallBottomService()

1.1 Synchronized Call Code

Synchronized call sequence diagram:

[Img-dapFATDy-1569148364574 (https://upload-images.jianshu.io/upload_images/3796264-6a5b5b898aa3930e.png? ImageMogr2/auto-orient/strip | imageView2/2/w/1031/format/webp)]

Synchronized Call Sequence Diagram

1.1.1 underlying service class: BottomService.java

package synchronization.demo;

/**

* Created by lance on 2017/1/19.

*/

public class BottomService {

public String bottom(String param) {

try { //  Simulating the underlying processing is time-consuming and the upper services need to wait

Thread.sleep(3000);

} catch (InterruptedException e) {

e.printStackTrace();

}

return param +" BottomService.bottom() execute -->";

}

}

1.1.2 Upper 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);

}

1.1.3 Upper Service Interface Implementation Class: UpperService Impl. 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 --> ");

}

}

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 for callBottomService() to call BottomService.bottom() method to return before it can execute.

upperService.upperTaskAfterCallBottomService(result);

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

}

}

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

Note the output:

In a synchronous manner, Test calls callBottomService() to wait for the execution to end, and then executes the next step, that is, the execution to end. Call Bottom Service 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, which is consistent with the simulation time, i.e. 3000 milliseconds.

Example two: from shallow to deep

The company interviewed a few days ago and asked the question of java callback, because there was not too much research in this area, so the answer was ambiguous. This time I intentionally came to remedy it. Looking at the explanation and examples of callbacks on the internet, we can see that it takes half a day to get around. In fact, callbacks are a very simple mechanism. Let me explain in a simple language: suppose there are two classes, A and B, there is a method a() in A and a method b(); method b() in A is called in B, and method a() is called in method b(), so that the functions of two methods b() and a() are realized at the same time.

Doubt: Why is it so troublesome? I call a() method directly under B.b() method in class A.
Answer: Callbacks are more like a convention that if I call the b() method, then I have to call back without displaying the call.
I. Java Callback - Shallow
We use an example to explain: Xiao Ming and Xiao Li make an appointment to have breakfast together, but Xiao Li gets up a little late and needs to wash first. After Xiao Li washes, he informs Xiao Ming to go to dinner again. Xiao Ming is class A, Xiao Li is class B. The event of going to dinner together is method a(), and Xiao Li's going to wash is method b().

public class XiaoMing { 
   //Xiao Ming and Xiao Li eat together
   public void eatFood() {
      XiaoLi xl = new XiaoLi();
      //A calls the method of B
      xl.washFace();
   }
 
   public void eat() {
      System.out.print("Xiao Ming and Xiao Li go to eat lobster together");
   }
}
//So how can Xiao Li go to dinner with Xiao Ming after washing up?

public class XiaoMing { 
   //Xiao Ming and Xiao Li eat together
   public void eatFood() {
      XiaoLi xl = new XiaoLi();
      //A calls the method of B
      xl.washFace();
      eat();
   }
 
   public void eat() {
      System.out.print("Xiao Ming and Xiao Li go to eat lobster together");
   }
}

But as mentioned above, this is not a callback function, so it can't be done in this way. The correct way is as follows.

public class XiaoLi{//petty thief
   public void washFace() {
    System.out.print("Xiao Li wants to wash and rinse");
    XiaoMing xm = new XiaoMing();
        //B Calls Method A
    xm.eat();//After washing, go to dinner together
   }
}

This enables washFace() and eat(). After Xiao Li washes and rinses, he informs Xiao Ming to go to dinner together. This is called back.

2. Java callbacks - in
However, careful partners may find that Xiao Li's code is completely written, so the occasion may be suitable for Xiao Ming to eat together, but if Xiao Li washes up and does not eat, and wants to go online with Xiao Wang, this is not applicable. In fact, the above is pseudo-code, just to help you understand, the real situation is the need to use the interface to set callbacks. Now let's continue with the example of Xiaoming and Xiaoli going to dinner to explain how the interface is used.

Xiao Ming and Xiao Li went to breakfast together, but Xiao Li got up a little late and had to wash first. After Xiao Li finished washing, he told Xiao Ming to go to dinner again. Xiao Ming is class A, Xiao Li is class B. The difference is that we create a new EatRice interface, which has an abstract method eat(). Xiao Ming calls the interface and implements eat(); Xiao Li declares the interface object and calls the abstract method of the interface. It may be a little bit tongue twister here, but it doesn't matter. Look at the example.

EatRice interface:

public interface EatRice {
   public void eat(String food);
}
//Xiao Ming:

public class XiaoMing implements EatRice{//Xiao Ming
    
   //Xiao Ming and Xiao Li eat together
   public void eatFood() {
    XiaoLi xl = new XiaoLi();
    //A calls the method of B
    xl.washFace("Lobster", this);//this refers to the EatRice interface implemented by Xiaoming class.
   }
 
   @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{//petty thief
   public void washFace(String food,EatRice er) {
    System.out.println("Xiao Li wants to wash and rinse");
        //B calls the method of A.
    er.eat(food);
   }
}
//Test Demo:

public class demo {
   public static void main(String args[]) {
    XiaoMing xm = new XiaoMing();
    xm.eatFood();
   }
}

Test results:

In this way, soft coding is realized through the form of interface. Through the form of interface, I can realize Xiao Li washing, and Xiao Wang go online together. The code is as follows

public class XiaoWang implements EatRice{//Xiao Wang
    
   //Xiao Wang and Xiao Li go online together
   public void eatFood() {
    XiaoLi xl = new XiaoLi();
    //A calls the method of B
    xl.washFace("Dancing and surfing the Internet", this);
   }
 
   @Override
   public void eat(String bar) {
    // TODO Auto-generated method stub
    System.out.println("Xiao Wang and Xiao Li are going together." + bar);
   }
}

Example 3: Tom does the problem

The math teacher asked Tom to do a question, and Tom did not focus on Tom while she was doing the math. Instead, she was playing with her mobile phone. After Tom finished the question, she told the teacher the answer.

1 Mathematics teacher needs a quotation from Tom before he can send the question to Tom.

Mathematics teacher needs to provide a method so that Tom can tell him the answer when he finishes the problem.

3 Tom needs a quotation from his 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 teacher interface

    //Callback means that A calls B to do one thing, B tells A the result after it is done, during which A can do something else.
    //There is A method in this interface, which means the method used when B tells A after finishing the topic.
    //So we have to provide this interface so that B calls back and forth.
    //Callback interface,
    public interface CallBack {
        void tellAnswer(int res);
    }


Mathematics Teachers

    //The teacher class instantiates the callback interface, that is, after the students have finished writing the questions, they can make callbacks through the method provided by the teacher.
    //So how do students call the teacher's method, as long as the teacher's reference is introduced into the student's method.
    //Teachers need to assign students to answer questions, so they also need to pass on students'examples.
public class Teacher implements CallBack{
    private Student student;

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

    void askProblem (Student student, Teacher teacher) {
        //The main method is that the main thread runs. To achieve an asynchronous callback, a thread is opened here to operate.
        new Thread(new Runnable() {
            @Override
            public void run() {
                student.resolveProblem(teacher);
            }
        }).start();
        //When the teacher asks the students to do the questions, they can do other things, such as playing cell phones, while waiting for students to answer.
        //Instead of waiting synchronously, this is the benefit of callbacks.
        //Of course, you can say that just open a thread and let the students do the questions, but this can not let the students inform the teacher.
        //Additional mechanisms are needed to implement the notification process.
        // Of course, future s and callable s in multithreading can also achieve the function of data acquisition.
        for (int i = 1;i < 4;i ++) {
            System.out.println("When the students answer the questions, the teacher plays " + i + "Second mobile phone");
        }
    }

    @Override
    public void tellAnswer(int res) {
        System.out.println("the answer is " + res);
    }
}

Student interface

    //The interface of students and the method of solving problems should be introduced into the teacher's reference, otherwise the callback of specific examples can not be completed.
    //The advantage of writing as an interface is that many students can implement it, and teachers can use it when asking questions.
    //It is very convenient to pass in List < Student > to aggregate students.
public interface Student {
    void resolveProblem (Teacher teacher);
}

Student Tom

public class Tom implements Student{

    @Override
    public void resolveProblem(Teacher teacher) {
        try {
            //After thinking for 3 seconds, the students got the answer and told 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();
        }
    }

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);
        //Result
//        When the students answered the questions, the teacher played the phone for one second.
//        When the students answered the questions, the teacher played the phone for 2 seconds.
//        When the students answered the questions, the teacher played the phone for 3 seconds.
//        work out
//        the answer is 111
    }
}

Reference articles

https://blog.csdn.net/fengye454545/article/details/80198446
https://blog.csdn.net/xiaanming/article/details/8703708/
https://www.cnblogs.com/prayjourney/p/9667835.html
https://blog.csdn.net/qq_25652949/article/details/86572948
https://my.oschina.net/u/3703858/blog/1798627

Public address

Java Technology

If you want to keep an eye on my updated articles and share the dry goods, you can pay attention to my public address [Java technology], a technology station of Ali Java engineer, author Huang Xiaoxie, focus on Java related technologies: SSM, SpringBoot, MySQL, distributed, middleware, cluster, Linux, network, multithreading, occasionally talk about Docker, ELK, and also share Technical dry goods and learning experience, committed to Java full stack development!

Java Engineers Necessary Learning Resources: Some Java Engineers commonly use learning resources. After paying attention to the public number, the keyword "Java" can be answered in the background for free without routine access.

Personal Public No. Huang Xiaoxiao

The author is a master of 985, an engineer of Ant Golden Wear JAVA, focusing on the JAVA back-end technology stack: SpringBoot, MySQL, distributed, middleware, micro-services, but also knows how to invest in finance, occasionally talk about the theoretical basis of algorithms and computing mechanisms, adhere to learning and writing, believe in the power of lifelong learning!

Programmer 3T technology learning resources: Some programmers learn technology resources package, after paying attention to the public number, the background reply keyword "information" can be free of charge without routine access.

Topics: Java github Mobile SpringBoot