Java基础篇:回调机制详解

Java基础篇:回调机制详解

一、什么是回调:

回调是一种双向的调用模式,程序模块之间通过这样的接口调用完成通信联系,回调的核心就是回调方将本身即this传递给调用方,这样调用方就可以在调用完毕之后再告诉回调方它想要知道的信息。

回调函数用于层间协作,上层将本层函数安装在下层,这个函数就是回调,而下层在一定条件下触发回调,例如作为一个驱动,是一个底层,他在收到一个数据时,除了完成本层的处理工作外,还将进行回调,它将这个数据交给上层应用层来做进一步处理,这在分层的数据通信中很普遍。其实回调和API非常接近,他们的共性都是跨层调用的函数。但区别是API是低层提供给高层的调用,一般这个函数对高层都是已知的;而回调正好相反,他是高层提供给底层的调用,对于低层他是未知的,必须由高层进行安装。这个安装函数其实就是一个低层提供的API,安装后低层不知道这个回调的名字,但它通过一个函数指针来保存这个回调,在需要调用时,只需引用这个函数指针和相关的参数指针。

 其实:回调就是该函数写在高层,低层通过一个函数指针保存这个函数,在某个事件的触发下,低层通过该函数指针调用高层那个函数。从调用方式上看,可以分为两类:同步回调、异步回调。

 

二、同步回调与异步回调:

1、同步回调:

同步调用是一种阻塞式调用,是最基本并且最简单的一种调用方式,类A的方法a()调用类B的方法b(),一直等待b()方法执行完毕,a()方法才能继续往下走。这种调用方式适用于方法b()执行时间不长的情况,因为b()方法执行时间一长或者直接阻塞的话,a()方法的余下代码是无法执行下去的,这样会造成整个流程的阻塞。

2、异步回调:

(1)异步调用是为了解决同步调用可能出现阻塞,导致整个流程卡住而产生的一种调用方式。类A的方法方法a()通过新起线程的方式调用类B的方法b(),代码接着直接往下执行,这样无论方法b()执行时间多久,都不会阻塞住方法a()的执行。但是这种方式,由于方法a()不等待方法b()的执行完成,在方法a()需要方法b()执行结果的情况下,必须通过一定的方式对方法b()的执行结果进行监听。为了完成这点,就需要另开一个线程了。

(2)异步调用在应用程序框架中具有广泛的应用,并且特指多线程情况下。它同Windows的消息循环机制,消息响应,消息队列,事件驱动机制以及设计模式中的观察者模式等都是紧密相关的。 在单线程方式下,计算机是一台严格意义上的冯·诺依曼式机器,一段代码调用另一段代码时,只能采用同步调用,必须等待这段代码执行完返回结果后,调用方才能继续往下执行。有了多线程的支持,可以采用异步调用,调用方和被调方可以属于两个不同的线程,调用方启动被调方线程后,不等对方返回结果就继续执行后续代码。被调方执行完毕后,通过某种手段通知调用方:结果已经出来,请酌情处理。异步回调常见于请求服务器数据,当取到数据时,会进行回调。

 

三、异步回调例子:

上面讲了那么多,其实所谓回调,就是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
  • A的对象a调用B的方法 f(CallBack callback) ——A类调用B类的某个方法 C
  • 然后b就可以在f(CallBack callback)方法中调用A的方法 ——B类调用A类的某个方法D

有一天小王遇到一个很难的问题,问题是“1 + 1 = ?”,就打电话问小李,小李一下子也不知道,就跟小王说,等我办完手上的事情,就去想想答案,小王也不会傻傻的拿着电话去等小李的答案吧,于是小王就对小李说,我还要去逛街,你知道了答案就打我电话告诉我,于是挂了电话,自己办自己的事情,过了一个小时,小李打了小王的电话,告诉他答案是2 

/**
 * 这是一个回调接口
 */
public interface CallBack {
	/**
	 * 这个是小李知道答案时要调用的函数告诉小王,也就是回调函数
	 * @param result 是答案
	 */
	public void solve(String result);
}
/**
 * 这个是小王
 * 实现了一个回调接口CallBack,相当于----->背景一
 */
public class Wang implements CallBack {
	/**
	 * 小李对象的引用
	 * 相当于----->背景二
	 */
	private Li li; 
 
	/**
	 * 小王的构造方法,持有小李的引用
	 * @param li
	 */
	public Wang(Li li){
		this.li = li;
	}
	
	/**
	 * 小王通过这个方法去问小李的问题
	 * @param question  就是小王要问的问题,1 + 1 = ?
	 */
	public void askQuestion(final String question){
		//这里用一个线程就是异步
		new Thread(new Runnable() {
			@Override
			public void run() {
				/**
				 * 小王调用小李中的方法,在这里注册回调接口
				 * 这就相当于A类调用B的方法C
				 */
				li.executeMessage(Wang.this, question); 
			}
		}).start();
		
		//小网问完问题挂掉电话就去干其他的事情了,诳街去了
		play();
	}
 
	public void play(){
		System.out.println("我要逛街去了");
	}
 
	/**
	 * 小李知道答案后调用此方法告诉小王,就是所谓的小王的回调方法
	 */
	@Override
	public void solve(String result) {
		System.out.println("小李告诉小王的答案是--->" + result);
	}
}
/**
 * 这个就是小李
 */
public class Li {
	/**
	 * 相当于B类有参数为CallBack callBack的f()---->背景三
	 * @param callBack  
	 * @param question  小王问的问题
	 */
	public void executeMessage(CallBack callBack, String question){
		System.out.println("小王问的问题--->" + question);
		
		//模拟小李办自己的事情需要很长时间
		for(int i=0; i<10000;i++){
			
		}
		
		/**
		 * 小李办完自己的事情之后想到了答案是2
		 */
		String result = "答案是2";
		
		/**
		 * 于是就打电话告诉小王,调用小王中的方法
		 * 这就相当于B类反过来调用A的方法D
		 */
		callBack.solve(result); 	
	}
}
/**
 * 测试类
 */
public class Test {
	public static void main(String[]args){
		/**
		 * new 一个小李
		 */
		Li li = new Li();
 
		/**
		 * new 一个小王
		 */
		Wang wang = new Wang(li);
		
		/**
		 * 小王问小李问题
		 */
		wang.askQuestion("1 + 1 = ?");
	}
}

 

参考博文:

https://blog.csdn.net/kobejayandy/article/details/17654967

https://blog.csdn.net/xiaanming/article/details/8703708

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/114682.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • pp图与qq图_画图python

    pp图与qq图_画图python统计学中有时会会用到PP图或QQ图

    2022年8月10日
    28
  • c#中的CultureInfo类[通俗易懂]

    c#中的CultureInfo类[通俗易懂]c#中的CultureInfo类2014年06月20日17:14:33DO_DAJIANGJUN阅读数:9912更多个人分类:C#/.NetFramework/.NetCore版权声明:本文为博主原创文章,未经博主允许不得转载。https://blog.csdn.net/XuWei_XuWei/article/details/32717259CultureInfo类位…

    2022年6月19日
    24
  • 家庭影院.液晶电视.液晶电视连接电脑全功略续[通俗易懂]

    家庭影院.液晶电视.液晶电视连接电脑全功略续[通俗易懂]家庭影院.液晶电视.液晶电视连接电脑全功略续草木瓜20090201一、前言 《家庭影院.液晶电视.液晶电视连接电脑全功略》http://blog.csdn.net/liwei_cmg/archive/2008/11/28/3402883.aspx 一文中介绍了使用三星32A550P1R,作为电脑外接显示器+音箱的方法。其中中提到了 使用1366*768的分辨率。32A550物理

    2022年10月19日
    0
  • linux安装卸载软件的命令_shell命令卸载软件

    linux安装卸载软件的命令_shell命令卸载软件linux卸载软件命令Linuxprovidesdifferentmethodsforinstallingsoftware.YoucaninstallsoftwarefromthestandardUbuntusoftwarerepositoriesusingtheUbuntuSoftwareCenter,fromoutsideofthestan…

    2022年9月10日
    0
  • echo -ne(echo line)

    echo[-ne][字符串]或echo[–help][–version]  补充说明:echo会将输入的字符串送往标准输出。输出的字符串间以空白字符隔开,并在最后加上换行号。  参  数:-n不要在最后自动换行       -e若字符串中出现以下字符,则特别加以处理,而不会将它当成一般        文字输出:        \a发出警告声;       

    2022年4月11日
    78
  • 贝叶斯公式的理解

    贝叶斯公式的理解作者:知乎用户链接:https://www.zhihu.com/question/21134457/answer/169523403来源:知乎著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。最近我自己在学习一些关于机器学习的东西,目前学到了贝叶斯统计这一块,我觉得很感兴趣,于是便找了一些资料看了看,在自己琢磨一段时间后,写了一篇博客,原文地址:机器学习(一)——浅谈贝叶斯和…

    2022年5月5日
    28

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号