概念
正常一个系统肯定存在模块之间的调用,一般调用分以下几种:
- 同步调用。 类A的方法a()调用类B的方法b(),然后一直等待b()方法执行结束,a()方法才能继续往下执行。
- 异步调用。 类A的方法a()调用类B的方法b(),然后a()方法自己继续往下执行,不用去管b()方法是否执行结束。
- 回调。 回调就是类A的方法a()调用类B的方法b(),然后类B的b()方法执行结束后也能调用类A的a()方法,简单讲即双向调用。同样回调也会分同步调用、异步调用。
案例
案例一 - 请求
此情况:我们调用访问客户端,然后客户端去请求服务端,服务端去查询数据,等数据查询完毕,再返回给客户端结果。
定义回调函数
CallBack.java
//回调函数
public interface CallBack {
public void sendMessage(String result);
}
回调函数我自己理解就是若类A方法调用类B方法,那就这个回调函数就是类B回调类A的一个函数,这里客户端调用服务端,这个回调函数就是服务端调用客户端的方法,即返回给客户端数据的方法。
客户端、服务端
Client.java
public class Client implements CallBack {
private Service service;
public Client(Service service){
this.service = service;
}
public void request(){
System.out.println("请求调用服服务端获取数据。");
//调用服务端的方法获取数据
service.sendMessage(this);
}
//接受服务端返回的数据
@Override
public void sendMessage(String result) {
System.out.println("服务端回调客户端方法返回的结果是:"
+result);
}
}
Service.java
public class Service {
public void sendMessage(Client client){
/*
* 模拟获取数据
* */
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//回调客户端,返回数据
client.sendMessage("服务端数据");
}
}
测试及结果
Test.java
public class Test {
public static void main(String[] args) {
Client client = new Client(new Service());
client.request();
}
}
结果
请求调用服服务端获取数据。
(暂停1s)
服务端回调客户端方法返回的结果是:服务端数据
案例二 - 老师询问学生(分为同步、异步)
定义回调函数
CallBack.java
public interface CallBack {
//学生回调老师的函数--回答老师
public void answear(String result);
}
学生、老师
Teacher.java
public class Teacher implements CallBack {
public Student student;
public Teacher(Student student){
this.student = student;
}
public void askQqstion(String question){
System.out.println("老师询问学生的问题:"+question);
//异步询问学生问题
//如果这里不用线程就是同步调用
new Thread(()->{
//学生思考老师的问题
student.thinkProblem(this,question);
}).start();
Correcting();
}
public void Correcting(){
System.out.println("我继续修改试卷");
}
@Override
public void answear(String result) {
System.out.println("回答老师的问题:"+result);
}
}
Student.java
public class Student {
public void thinkProblem(CallBack callBack,String question){
System.out.println("学生听到老师的问题,我需要思考3秒钟。");
//模拟思考
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//思考了半天得到了答案
String result = "200";
//调用回调函数,告诉老师答案
callBack.answear(result);
}
}
测试及结果
Test.java
public class Test {
public static void main(String[] args) {
Teacher teacher = new Teacher(new Student());
//老师询问问题
teacher.askQqstion("100+100等于几?");
}
}
同步结果:
老师询问学生的问题:100+100等于几?
学生听到老师的问题,我需要思考3秒钟。
(暂停3s)
回答老师的问题:200
我继续修改试卷
上述可知,老师修改试卷需要学生回答之后才能继续,不然就一直等学生回答,即为同步回调。
异步结果:
老师询问学生的问题:100+100等于几?
我继续修改试卷
学生听到老师的问题,我需要思考3秒钟。
(暂停3s)
回答老师的问题:200
这里就是老师问完之后,不等学生回答就继续修改试卷,学生思考完告诉老师,即为异步回调。
总结
从这几个例子来看,回调函数其实也挺好理解的,简单理解就是回调函数就是由调用方自己具体实现,然后提供给被调用方调用的一个特殊函数。Java多线程中的Future、Callable、FutureTask其实就是这种回调机制。