Java中的异步和同步回调
回调函数是一个函数,它作为参数传递给另一个函数,并预计在某种事件之后执行。回调函数的目的是通知类 Sync/Async 是否完成了另一个类中的某些工作。这在处理异步任务时非常有用。假设我们想要执行一些日常任务,例如在单击按钮后执行某些操作或显示内容,或者从 Internet 获取数据。这也用于事件处理,因为当通过回调函数单击按钮时我们会收到通知。
这种类型的设计模式用于观察者设计模式。观察者模式是一种软件设计模式,其中一个称为主体的对象维护其依赖项(称为观察者)的列表,并自动通知它们任何状态更改,通常通过调用他们的一种方法(来源:wiki)。
在Java中,可以使用接口实现回调。实施的一般程序如下。
1. Define the methods in an interface that we want to invoke after callback.
2. Define a class that will implement the callback methods of the interface.
3. Define a reference in other class to register the callback interface.
4. Use that reference to invoke the callback method.
同步回调
代码执行将在继续之前阻塞或等待事件。在您的事件返回响应之前,您的程序将不会继续执行。所以基本上,回调在返回调用语句之前执行所有工作。同步回调的问题在于它们似乎滞后。
下面是这个原理的简单实现
// Java program to illustrate synchronous callback
interface OnGeekEventListener {
// this can be any type of method
void onGeekEvent();
}
class B {
private OnGeekEventListener mListener; // listener field
// setting the listener
public void registerOnGeekEventListener(OnGeekEventListener mListener)
{
this.mListener = mListener;
}
// my synchronous task
public void doGeekStuff()
{
// perform any operation
System.out.println("Performing callback before synchronous Task");
// check if listener is registered.
if (this.mListener != null) {
// invoke the callback method of class A
mListener.onGeekEvent();
}
}
// Driver Function
public static void main(String[] args)
{
B obj = new B();
OnGeekEventListener mListener = new A();
obj.registerOnGeekEventListener(mListener);
obj.doGeekStuff();
}
}
class A implements OnGeekEventListener {
@Override
public void onGeekEvent()
{
System.out.println("Performing callback after synchronous Task");
// perform some routine operation
}
// some class A methods
}
输出:
Performing callback before synchronous Task
Performing callback after synchronous Task
异步回调
异步调用不会阻止程序执行代码。当调用从事件返回时,调用返回回调函数。因此,在Java的上下文中,我们必须创建一个新线程并在该线程内调用回调方法。回调函数可以从线程调用,但不是必需的。 Callback 也可以启动一个新线程,从而使它们自己异步。
下面是这个原理的简单实现。
// Java program to illustrate Asynchronous callback
interface OnGeekEventListener {
// this can be any type of method
void onGeekEvent();
}
class B {
private OnGeekEventListener mListener; // listener field
// setting the listener
public void registerOnGeekEventListener(OnGeekEventListener mListener)
{
this.mListener = mListener;
}
// My Asynchronous task
public void doGeekStuff()
{
// An Async task always executes in new thread
new Thread(new Runnable() {
public void run()
{
// perform any operation
System.out.println("Performing operation in Asynchronous Task");
// check if listener is registered.
if (mListener != null) {
// invoke the callback method of class A
mListener.onGeekEvent();
}
}
}).start();
}
// Driver Program
public static void main(String[] args)
{
B obj = new B();
OnGeekEventListener mListener = new A();
obj.registerOnGeekEventListener(mListener);
obj.doGeekStuff();
}
}
class A implements OnGeekEventListener {
@Override
public void onGeekEvent()
{
System.out.println("Performing callback after Asynchronous Task");
// perform some routine operation
}
// some class A methods
}
输出:
Performing operation in Asynchronous Task
Performing callback after Asynchronous Task
什么时候用什么
同步回调:任何具有多个任务且任务必须按顺序执行且不占用太多时间的进程都应使用同步回调。
例如:你在排队买票,直到你前面的每个人都拿到一张,你才能拿到一张。
异步回调:当任务不相互依赖并且可能需要一些时间来执行时,我们应该使用异步回调。
例如:当您点餐时,其他人也可以在餐厅点餐。他们不必等待您的订单完成,如果您从互联网下载歌曲,获取 API 响应。
参考:
https://www.javaworld.com/article/2077462/learn-java/java-tip-10–implement-callback-routines-in-java.html
https://en.wikipedia.org/wiki/Callback_(computer_programming)