回调机制是一个非常有趣的机制,我对于回调的简单理解就像是一种责任委托一样
回调的简单定义是: F类调用了H类的某个方法c,而H类反过来调用F类的d,d就是回调方法。
下面先通过第一个简单的静态回调例子来讲解回调,然后对比流行的实例回调:
该场景是: 假如B向A发送“削苹果”的指令,A需要完成该任务。完成后,A通知B,B将对A的结果做出反应。
在实现中,可能A完成指令时,B有其他任务,所以我们考虑使用一个线程来实现A的任务。这样B就不能阻塞在A完成任务时。在视线中,我们考虑通过使用回调来实现A对
B的通知,这样有很大的便利。先看实现:
代码实现如下:
class CallBackA implements Runnable{
String command="";
public CallBackA(String command){
this.command = command;
System.out.println("A:收到消息:"+command);
System.out.println("A: 完成后,我通知B");
};
public void run(){//使用多线程实现A的任务
System.out.println("A: 正在完成");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("A: 已经完成 通知B");
CallBackB.receive(command+"完成");
}
}
public class CallBackB {
public static void receive ( String message)//A回调B的方法
{
System.out.println("B:收到A的完成消息: "+message);
System.out.println("B:我吃苹果");
}
public CallBackB() {
// TODO Auto-generated constructor stub
}
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("B: A削苹果给我,我等你完成");
CallBackA call = new CallBackA ("削苹果");
new Thread(call).start();
}
}
运行结果:
在代码实现中,B在向A发送指令后,A开启线程调用run()方法完成任务。并在完成指令后调用了B的静态方法receive(),就是通知了B自己完成了任务。其中A调用B的receive()方法称为回调方法。该实现使用回调实现A通知B的技巧在于不是B采用轮询重复地询问A是否完成任务(就像一个五岁小孩在长途汽车旅行中反复地问"我们到了吗?") 而是让线程A告诉主程序B何时结束。这是通过调用主类中的一个方法实现的。就是回调,这样主程序可以瞪大线程结束期间休息,而且不会占用线程的时间当线程的run()方法接近结束时,要做的最后一件事就是基于结果调用主程序的一个已知方法。不是由主程序询问每个线程来寻求答案,而是每个线程告知主程序答案。
在该实现中,A调用B的静态方法,所以该实现也是回调静态实现。但是,一般通用的是回调的实例实现,
使用实例方法带替静态方法进行回调要复杂一些,下面是实例实现的代码
*
*
class CallBackC implements Runnable{
String command;
CallBackD call;
public CallBackC(String command, CallBackD call)
{
this.command = command;
this.call = call;
};
public void run()
{
System.out.println("C: 接受到来自D的指令:"+command);
System.out.println("C: 正在处理");
System.out.println("C: 处理完成 将通知D");
call.receive("削苹果完成");
}
}
public class CallBackD {
public CallBackD() {
// TODO Auto-generated constructor stub
}
public void receive(String result)
{
System.out.println("D: 收到来自C的消息: "+result);
System.out.println("D: 我吃苹果");
};
public static void main(String[] args) {
System.out.println("B: A削苹果给我,我等你完成");
CallBackD callD = new CallBackD ();
CallBackC callC = new CallBackC ("削苹果",callD);//将callD传入Callc,用于回调
new Thread(callC).start();
}
}
实例实现回调跟静态不同的是,需要将callD本身传入callC,callC得到了callD的对象后,callC就可以通过callD回调callD的方法。实例回调方法更加灵活,可以涉及多个线程,对象和类的更复杂的情况。例如如果有多个对象对CallBackC的削成的苹果感兴趣,那个线程可以保存一个回调 的对象列表。特定的对象课一调用Runnable类的方法把自己添加到这个列表中完成注册,表示对削成的苹果感兴趣。当然,每个对象需要声明自己的回调方法,这可以通过定义一个回调接口,那些对象实现就可以了,这种机制就是著名的观察者模式,大家可以自己去研究一下。