Series 11 Java lay a solid foundation: in-depth understanding of the callback mechanism in Java

This series of articles will arrange to me on GitHub's "Java Interview Guide" warehouse, more exciting content please go to my warehouse View

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

Like it under the trouble spots Star Kazakhstan

Article first appeared in my personal blog:

www.how2playlife.com

This article is a micro-channel public number [of] Java technology quack "reinforce the Java Foundation series Bowen," in which a Part of this article from the network, to the subject of this article speaks clear and thorough, and I think a lot of good integration of technology blog content, which cited a number of good blog posts, if infringement, please contact the author. This blog series will show you how to from entry to advanced, step by step to learn the basics of Java, and started actual combat, then understand Java knowledge to realize the principles behind each point, a more complete understanding of the entire Java technology system, to form their own intellectual framework. In order to summarize and test your learning outcomes, this series will provide every knowledge point corresponding interview questions and suggested answers.

If you have any suggestions for this series of articles, or have any questions, you can also concerned about the number of public rivers and lakes [] Java technology to contact the author, you are welcome to participate in the creation and revision of this blog series.

@ [Heel]

Calls between modules

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

In one application, regardless of what language to use to develop, there must be invoked between modules, divided into several call:

(1) synchronous call

Synchronous call is the most basic and simplest way to call a class A method a () method calls the class B b (), have been waiting b () method is finished, a () method continues to go down. This method is applicable to the method call b () execution time is not long, because b () method performs over time or just jam, the remaining code is a () method is unable to perform down, this will cause the entire process obstruction.

(2) an asynchronous call

In order to solve the asynchronous call is a synchronous call blocking might occur, lead to a way of calling the entire process stuck produced. A class of methods a () method of class B call B () by way of starting a new thread, then the code executed directly downward, so that regardless of method B () execution time is long, will not clog up in the method a () of carried out.

In this manner, however, since the method a () Method B without waiting () is executed, in the process of a () Method B requires () in the case of the execution result (depending on the specific service may be, for example some operational start issuing asynchronous thread micro-channel notification, there is no need to refresh such a cache), the listener must be some way by the method execution result B () a.

In Java, you can use the Future + Callable way to do this, the specific approach can be found in my article Java multi-threaded 21: multithreaded CyclicBarrier of other components, Callable, Future and FutureTask.

(3) callback

1. What is callback? In general, there is a certain relationship between the calling module, from the point of view is called, it can be divided into three categories synchronous calls, asynchronous calls and callbacks. Synchronous call is a call blocking, i.e., the function to call the function A in the body by the function name written in the function B, the code in the memory that corresponds to the function B is performed. The latter is an asynchronous call or message mechanism similar events solves the problem of synchronization obstruction, such as B after A notice, they each go their own way, independently of each other, did not like synchronous call, notification B A, B have to wait until the go after, A before continuing to walk. Callback is a two-way call mode, that is to say, to be called the interface will call the other side of the interface is called, for example, A call to B, B to call again after executing A.

2, the use of callbacks callbacks interlayer cooperation is generally used, the upper layer is present underlying function is installed, this is a callback function, and the lower trigger callback under certain conditions. For example, as a driver, is a bottom, when he receives a data, in addition to complete the processing of this layer, will also call back this data to the upper application layer to do further processing, in which the hierarchical data communication is very common.

Multi-thread "callback"

The return value in a multi-threaded Java thread execution can be obtained through a combination of callable and future or futuretask post. To achieve this is to call the call callable method to get the return value of the get method.

In fact, the essence of this approach is not a callback, the callback is required after the task is completed by the caller initiative caller callback interface. And here is the caller blocked the initiative to use the get method to obtain the return value.

public class 多线程中的回调 {
    //这里简单地使用future和callable实现了线程执行完后
    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";
            }
        });
        //手动阻塞调用get通过call方法获得返回值。
        System.out.println(future.get());
        //需要手动关闭,不然线程池的线程会继续执行。
        executor.shutdown();

    //使用futuretask同时作为线程执行单元和数据请求单元。
    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();
    //阻塞获取返回值
    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 combat

Had occasionally heard myself callback mechanism, able to understand some vague sense, but when writing yourself a simple example program that he was dumbfounded. With increasing experience, we often heard here use a callback, where the use of callback, he is a good time to look at the Java callback mechanism. Online articles about Java callback grasping a lot, but after reading always foggy and incomprehensible, especially to see crawling someone else's code take two steps, always disgraced. So I decide to write an article about Java mechanism to facilitate more in-depth study and their own Java callback mechanism.

First, what is a callback function, cited explanation Baidu Encyclopedia: The callback function is a function call through a function pointer. If you put the pointer (address) function as a parameter to another function, when the pointer is used to call the function it points to, we say this is a callback function. Callback function is not called directly by the parties to achieve the function, but by another calling party when a particular event or condition occurs, in response to the event or condition [2].

Sorry, the above explanation I read it several times, did not understand the profound mystery which, I believe some of you readers, too. Handle and a spout lip off, let's understand the context of actual combat.

Example one: a synchronous call

In this paper, the upper layer and the underlying service BottomService UpperService service as an example, using the bottom of the upper layer service call service, overall implementation process is as follows:

Step 1: Execute UpperService.callBottomService ();

The second step: the implementation of BottomService.bottom ();

The third step: the implementation of UpperService.upperTaskAfterCallBottomService ()

1.1 synchronous calling code

Synchronous call timing diagram:

[Image dump outer link failure (img-dapFATDy-1569148364574) (https://upload-images.jianshu.io/upload_images/3796264-6a5b5b898aa3930e.png?imageMogr2/auto-orient/strip|imageView2/2/w/1031 / format / webp)]

Synchronous call timing diagram

1.1.1 the underlying service categories: BottomService.java

package synchronization.demo;

/**

* Created by lance on 2017/1/19.

*/

public class BottomService {

public String bottom(String param) {

try { //  模拟底层处理耗时,上层服务需要等待

Thread.sleep(3000);

} catch (InterruptedException e) {

e.printStackTrace();

}

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

}

}
复制代码

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

}
复制代码

1.1.3 upper service interface implementation class: UpperServiceImpl.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执行必须等待callBottomService()调用BottomService.bottom()方法返回后才能够执行

upperService.upperTaskAfterCallBottomService(result);

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

}

}
复制代码

1.1.5 Output:

=============== 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 that the output results:

Synchronous mode, Test call callBottomService () waits for the end of execution, then the next step, i.e. the end. callBottomService execution start time is Thu Jan 19 14:59:58 CST 2017, the end of the execution time is Thu Jan 19 15:00:01 CST 2017, takes 3 seconds, consistent with the time-consuming simulation of time, i.e. 3000 milliseconds.

Example 2: Deep

A few days ago the company has asked interview questions java callback, because not much research in this area, so the answer is vague, this time specifically to cram it. Looked callback explanations and examples online, we are so convoluted, have half a day to look around the back, in fact it, the callback is a very simple mechanism. Here, I first language simple explain: Suppose there are two categories, namely A and B, there is a method A in A (), B is a B method (); in which A is calling B method b (), and b method () calls a method of a (), while this way to achieve a b () and a () function of two methods.

Wondering: Why so much trouble, I call a () in class A Bb directly under the () methods on the line chanting. ANSWER: The callback is more like a convention, that is, if I call b () method, then it must be a callback, without the need to invoke a display, Java callback - shallow we use an example to explain: Xiao Ming and Li together to meet eat breakfast, but Mike played a little late first wash, wash, etc. after Mike completed, notice Xiao Ming went out to dinner again. Xiao Ming is a class A, class is Mike B. Went out to dinner this event is the way a (), Mike method is to wash b ().

public class XiaoMing { 
   //小明和小李一起吃饭
   public void eatFood() {
      XiaoLi xl = new XiaoLi();
      //A调用B的方法
      xl.washFace();
   }
 
   public void eat() {
      System.out.print("小明和小李一起去吃大龙虾");
   }
}
那么怎么让小李洗漱完后在通知小明一起去吃饭呢

public class XiaoMing { 
   //小明和小李一起吃饭
   public void eatFood() {
      XiaoLi xl = new XiaoLi();
      //A调用B的方法
      xl.washFace();
      eat();
   }
 
   public void eat() {
      System.out.print("小明和小李一起去吃大龙虾");
   }
}复制代码

But I have already said this is not a callback function, it is not this way, the right way is as follows

public class XiaoLi{//小李
   public void washFace() {
    System.out.print("小李要洗漱");
    XiaoMing xm = new XiaoMing();
        //B调用A的方法
    xm.eat();//洗漱完后,一起去吃饭
   }
}复制代码

This way you can achieve washFace () also enables eat (). Li after washing, and then notify the Xiao Ming went out to dinner, this is a callback.

Two, Java callback - but in a careful partner may find Mike's code is written completely dead, with such a situation that may be applicable and Bob went out to dinner, but if Mike does not wash finished dinner, think and Wang go online, like this do not apply. In fact, the above pseudo-code, just to help you understand, the situation is under real need to use the interface to set the callback. Now we continue with the example of Bob and Mike to dinner to say something about how to use the interface.

Xiao Ming and Li get together to eat breakfast, but Mike played a little late first wash, wash, etc. After Mike completed, notice Xiao Ming went out to dinner again. Xiao Ming is a class A, class is Mike B. The difference is that we create a meal interface EatRice, the interface has an abstract method eat (). Call Bob in this interface, and realize eat (); Li declare this interface object and calls the abstract methods of the interface. Here may be a bit convoluted, but it does not matter, look at the example becomes clear.

EatRice Interface:

public interface EatRice {
   public void eat(String food);
}
小明:

public class XiaoMing implements EatRice{//小明
    
   //小明和小李一起吃饭
   public void eatFood() {
    XiaoLi xl = new XiaoLi();
    //A调用B的方法
    xl.washFace("大龙虾", this);//this指的是小明这个类实现的EatRice接口
   }
 
   @Override
   public void eat(String food) {
    // TODO Auto-generated method stub
    System.out.println("小明和小李一起去吃" + food);
   }
}
小李:

public class XiaoLi{//小李
   public void washFace(String food,EatRice er) {
    System.out.println("小李要洗漱");
        //B调用了A的方法
    er.eat(food);
   }
}
测试Demo:

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

Test Results:

This way is realized in the form of soft-coded interface. In the form of interface I can be achieved after washing Li, and Wang went to the Internet together. code show as below

public class XiaoWang implements EatRice{//小王
    
   //小王和小李一起去上网
   public void eatFood() {
    XiaoLi xl = new XiaoLi();
    //A调用B的方法
    xl.washFace("轻舞飞扬上网", this);
   }
 
   @Override
   public void eat(String bar) {
    // TODO Auto-generated method stub
    System.out.println("小王和小李一起去" + bar);
   }
}复制代码

Three examples: Tom do problems

The teacher asked Tom to do a math problem, and Tom do the math teacher during the problem without looking at Tom, but in the play phone, and other topics Tom finished before the teacher told the answer.

1 math teacher Tom needs a reference, and then sent to the topic Tom.

2 math teachers need to provide a method to be able to tell him the answer after Tom finished title.

3 Tom math teacher needs a reference to Tom the answer to the teacher, rather than a physical education teacher next door.

Callback interface, the interface can be understood as a teacher

    //回调指的是A调用B来做一件事,B做完以后将结果告诉给A,这期间A可以做别的事情。
    //这个接口中有一个方法,意为B做完题目后告诉A时使用的方法。
    //所以我们必须提供这个接口以便让B来回调。
    //回调接口,
    public interface CallBack {
        void tellAnswer(int res);
    }复制代码


Math teacher class

    //老师类实例化回调接口,即学生写完题目之后通过老师的提供的方法进行回调。
    //那么学生如何调用到老师的方法呢,只要在学生类的方法中传入老师的引用即可。
    //而老师需要指定学生答题,所以也要传入学生的实例。
public class Teacher implements CallBack{
    private Student student;

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

    void askProblem (Student student, Teacher teacher) {
        //main方法是主线程运行,为了实现异步回调,这里开启一个线程来操作
        new Thread(new Runnable() {
            @Override
            public void run() {
                student.resolveProblem(teacher);
            }
        }).start();
        //老师让学生做题以后,等待学生回答的这段时间,可以做别的事,比如玩手机.\
        //而不需要同步等待,这就是回调的好处。
        //当然你可以说开启一个线程让学生做题就行了,但是这样无法让学生通知老师。
        //需要另外的机制去实现通知过程。
        // 当然,多线程中的future和callable也可以实现数据获取的功能。
        for (int i = 1;i < 4;i ++) {
            System.out.println("等学生回答问题的时候老师玩了 " + i + "秒的手机");
        }
    }

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

Student Interface

    //学生的接口,解决问题的方法中要传入老师的引用,否则无法完成对具体实例的回调。
    //写为接口的好处就是,很多个学生都可以实现这个接口,并且老师在提问题时可以通过
    //传入List<Student>来聚合学生,十分方便。
public interface Student {
    void resolveProblem (Teacher teacher);
}复制代码

Student Tom

public class Tom implements Student{

    @Override
    public void resolveProblem(Teacher teacher) {
        try {
            //学生思考了3秒后得到了答案,通过老师提供的回调方法告诉老师。
            Thread.sleep(3000);
            System.out.println("work out");
            teacher.tellAnswer(111);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }复制代码

Test category

public class Test {
    public static void main(String[] args) {
        //测试
        Student tom = new Tom();
        Teacher lee = new Teacher(tom);
        lee.askProblem(tom, lee);
        //结果
//        等学生回答问题的时候老师玩了 1秒的手机
//        等学生回答问题的时候老师玩了 2秒的手机
//        等学生回答问题的时候老师玩了 3秒的手机
//        work out
//        the answer is 111
    }
}复制代码

Reference article

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

Micro-channel public number

Java technology rivers and lakes

If you want to focus on my real time updated articles and dry sharing, you can focus on my public number of rivers and lakes] [Java technology Java, a technical engineer Ali station, the author Huang oblique, focused Java related technologies: SSM, SpringBoot , MySQL, distributed, middleware, cluster, Linux, network, multi-threaded, occasionally speaking point Docker, ELK, as well as dry goods and technology to share the learning experience, committed to the full Java stack development!

Java engineers required Learning Resources: Some Java engineers common learning resources, the number of public attention, background replies keyword "Java" to get free no routine.

My public number

Personal Public Number: Huang oblique

The author is Master 985, ants gold dress JAVA engineer, specializing in JAVA backend technology stack: SpringBoot, MySQL, distributed, middleware, services, but also understand the point of investment banking, occasionally speaking point algorithms and theoretical basis of computer, keep learning and writing, believe in the power of lifelong learning!

Programmers 3T Technology Learning Resources: Some programmers learning resources spree technology, the number of public attention, background replies keyword "data" can get free no routine.

Guess you like

Origin juejin.im/post/5d9ae9405188251e3a06b9bd