最近有用到guava包的并发类,发现里面大量的用到了回调函数,突然就发现好多地方都用到了回调函数用到的思想,顺便就整理了一下,搞明白了回调函数是个什么东西。
简单点说,回调就是:A类中调用B类中的某个方法c,然后B类中反过来调用A类中的方法d,d这个方法就叫回调方法。这样子说可能刚开始看不能理解,其实我刚开始也是这样不理解,看了人家说比较经典的回调方式:
- Class A实现接口CallBack callback——背景1
- Class A中包含一个class B的引用b ——背景2
- Class B有一个参数为callback的方法f(CallBack callback) ——背景3
- Class A的对象a调用Class B的方法 f(CallBack callback) ——A类调用B类的某个方法 c
- 然后b就可以在f(CallBack callback)方法中调用A的方法——B类调用A类的某个方法D
这样解释是不是就好理解多了呢。下面我也举个例子来说明回调:比如小娄在寝室有点急事,但是这个时候有个快递到了,并且快递里面的东西得送到李老师手中,于是小娄就给小蒋打电话让他帮忙取一下快递然后带给李老师。但是这时候小蒋刚好正在食堂吃饭,他不可能端着饭就去取快递,于是就说,你等我吃完饭了帮你去快递给李老师。这时候小娄不可能一直拿着电话等消息,于是小娄就对小蒋说,你给老师了给我回个消息,然后去做自己的事了。过了半个小时,小蒋去了快递也给了李老师,就给小娄回了个电话通知他快递已经送达。
这个异步回调的实现源码:
package callback;
/**
* 这是一个回调接口
*/
public interface CallBack {
/**
* 这个是小蒋将快递送到之后要通知小娄的消息;
* 也就是回调函数
* @param result
*/
public void solve(String result);
}
小娄类
package callback;
/**
* Created by louyuting on 17/1/29.
* 这个是小娄
* 实现了一个回调接口CallBack,相当于----->背景一
*/
public class Lou implements CallBack {
//包含一个小蒋的引用----背景2
private Jiang jiang;
public Lou(Jiang jiang) {
this.jiang = jiang;
}
/**
* 小娄通过这个方法给小蒋布置任务.
* @param question
*/
public void askQuestion(final String question){
System.out.println("小娄问的问题--->" + question);
//这里用一个线程就是异步回调了,
new Thread(new Runnable() {
@Override
public void run() {
/**
* 小娄调用小李中的方法,在这里注册回调接口
* 这就相当于A类调用B的方法c
*/
jiang.executeMessage(Lou.this, question);
}
}).start();
//小娄说了task就去做自己的事了
play();
}
public void play(){
System.out.println("小娄给小蒋交代了任务就去做自己的事了.");
}
@Override
public void solve(String result) {
System.out.println("小蒋告诉小娄的回信--->" + result);
}
}
小蒋类:
package callback;
import java.util.concurrent.TimeUnit;
/**
* Created by louyuting on 17/1/29.
* 小蒋
*/
public class Jiang {
/**
* 相当于B类有参数为CallBack callBack的f()---->背景三
* @param callBack
* @param question 小娄的问题
*/
public void executeMessage(CallBack callBack, String question){
//模拟小李吃饭
for(int i=0; i<10000;i++){
try {
TimeUnit.MILLISECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("小蒋吃完了饭,然后取完快递给李老师了");
String result = "小蒋已经把快递给了老师!";
/**
* 于是就打电话告诉小娄,调用小娄中的方法
* 这就相当于B类反过来调用A的方法 d
*/
callBack.solve(result);
}
}
测试类:
package callback;
/**
* Created by louyuting on 17/1/29.
*/
public class ClientTest {
public static void main(String[] args) {
Jiang jiang = new Jiang();
Lou lou = new Lou(jiang);
lou.askQuestion("帮我取快递给老师");
}
}
运行结果:
上面执行逻辑就是:
1)小娄给小蒋打电话拜托取快递给老师;
2)然后new 线程 ,小蒋来解决任务;
3)小娄通知完之后就做自己的事;
4)小蒋完成了小娄拜托的任务之后,异步通知小娄他已完成任务;
5)小娄收到消息,得知小蒋已经解决了他的问题。