北京这周终于凉快了不少,舒了一口气,但是中暑带来的后遗症还没减轻,晕晕乎乎地上了一周的班也不见好转,基本就是这状态:

程序员

好了,不扯了。上篇文章讲了回调的基本原理:调用方通过方法将自己身的实例传给被调用方,被调用方拿到实例之后,就可以将结果返回给调用方了。

不知道大家看了上一篇文章之后会不会觉得哪里怪怪的,有点蹩脚。蹩脚的原因在于,XueMei的实例里面其实有一个XueZhang的对象,那么回调的过程其实还是在一个线程里面,自己跟自己的方法打转,该等待的还是要等待啊,并没有达到让学妹不要等待的目的。

为了让大家一目了然,我们把代码修改一下:

学妹的问问题方法:

public void askQuetion(){

System.out.println("I have a question");

Date start = new Date();

xueZhang.processQuestion(this);

System.out.println((new Date().getTime() - start.getTime())/1000+"s:"+"I'v got it,then do another job");

}

学长的回答问题方法:

public void processQuestion(CallBack callBack) {

try {

Thread.sleep(10000);

} catch (InterruptedException e) {

e.printStackTrace();

}

callBack.onResult( "zhi ge hao shuai");

}

结果:

result.png

可以看到中间是间隔了10s的,学妹才去做的其他事情,其实这就是一种同步回调的方式,所以感觉起来会很蹩脚。当然我觉得同步回调有一种用处就在于:可以立马返回一个结果给调用方。

在XueZhang的代码中加一行:

public void processQuestion(CallBack callBack) {

callBack.onResult("I receive your question");

try {

Thread.sleep(10000);

} catch (InterruptedException e) {

e.printStackTrace();

}

callBack.onResult( "zhi ge hao shuai");

}

结果:

result.png

我们就可以通过这个立马返回的结果知道被调用方已经收到我的请求,我可以安心去做其他事了。

那么,真正达到可以让调用方不等待的话,那就是异步回调。其实我才想起来在学前端和Andorid的时候,会经常接触到onCreate()方法,这就是回调的运用啊。

我们修改XueZhang的代码:

public void processQuestion(CallBack callBack) {

new Thread(new Runnable() {

@Override

public void run() {

try {

Thread.sleep(10000);

} catch (InterruptedException e) {

e.printStackTrace();

}

callBack.onResult("zhi ge hao shuai");

}

}).start();

}

新起一个线程,当执行完了自己通知,于是结果就是这样了:

result3.png

看到了吧,学妹终于可以干自己的事情了,不用等那个装逼的学长的答案了。

可以的话,回顾一下我之前写的关于同步与异步,阻塞与非阻塞的关系,当时其实是有一个遗留问题的:异步操作既然是被调用方在执行结束后通知调用方,那究竟要怎么通知呢?现在相信你有了答案。

嗯,你以为就结束了吗?

不,我们可能还是在单机上转悠啊,现在做的大部分系统,都是分布式的,我们得赶紧从学校学的那种前端加后端的模式中跳出来。

先给大家开个头吧,这样理解,我们调用的服务已经从一个臃肿的垂直架构中抽离出来了,也就是服务的运行有自己的环境,你要调用服务的服务不在你本地,怎么办呢?

大概有这么几种方式:

1.RPC。这是运用广泛的一种模式。通常会借助一个服务管理中心,管理各种在线服务,如阿里的dubbo。

2.REST。我们的调用当然还可以采用网络传输的方式啊,所以restful风格的这种API就大行其道啊,当然网络其实是最不靠谱的。

3.消息队列。MQ,Kafka,这类的东西的思想就是,我把要做的任务推(Push)到topic里面,消费者自己去拉(Pull)吧。

既然这样,我们回调通常也有这种跨机器的回调模式了。

分享一段国内开源框架LTS的代码(我其实也没深看):

SubmitCallback submitCallback = new SubmitCallback() {

@Override

public void call(RemotingCommand responseCommand) {

if (responseCommand == null) {

response.setFailedJobs(jobs);

response.setSuccess(false);

response.setMsg("Submit Job failed: JobTracker is broken");

LOGGER.warn("Submit Job failed: {}, {}", jobs, "JobTracker is broken");

return;

}

if (JobProtos.ResponseCode.JOB_RECEIVE_SUCCESS.code() == responseCommand.getCode()) {

if (LOGGER.isDebugEnabled()) {

LOGGER.debug("Submit Job success: {}", jobs);

}

response.setSuccess(true);

return;

}

// 失败的job

JobSubmitResponse jobSubmitResponse = responseCommand.getBody();

response.setFailedJobs(jobSubmitResponse.getFailedJobs());

response.setSuccess(false);

response.setCode(JobProtos.ResponseCode.valueOf(responseCommand.getCode()).name());

response.setMsg("Submit Job failed: " + responseCommand.getRemark() + " " + jobSubmitResponse.getMsg());

LOGGER.warn("Submit Job failed: {}, {}, {}", jobs, responseCommand.getRemark(), jobSubmitResponse.getMsg());

}

};

if (SubmitType.ASYNC.equals(type)) {

asyncSubmit(requestCommand, submitCallback);

} else {

syncSubmit(requestCommand, submitCallback);

}

不用关注逻辑,就看结构。有个内部类,或者说是匿名内部类获取SubmitCallback的对象,之后会通过同步和异步的方式发到另外的机器上处理请求。

之后的代码太多,我就不上传了,大概是:

异步的方式会将一个CallBack的实例一直往下传,而同步的方法则是选择等待一个返回值,从方法名就可以看出来:

public RemotingCommand invokeSync(RemotingCommand request)

public void invokeAsync(RemotingCommand request, AsyncCallback asyncCallback)

一个有返回值,一个没返回值。有兴趣的自己下着看一下,我研究的也不深,而且还有一些小疑问,等解决了之后再更吧。

回调太多就会使系统耦合加深,所以在单机的项目下还是少用吧。另外异步还有一种方式:Future,这感觉也是怪怪的,下次再讲。周末愉快,哦不,暑假愉快!哭,我还要上班!!!!

java回调与异步_Java同步异步玩转回调机制相关推荐

  1. httpclient java 异步_Java的异步HttpClient

    原文:http://www.cnblogs.com/guogangj/p/5462594.html 上篇提到了高性能处理的关键是异步,而我们当中许多人依旧在使用同步模式的HttpClient访问第三方 ...

  2. java单线程异步_Java 实现异步调用

    首先 我遇到的问题是 接口调用时需要更新缓存 而更新缓存又是个说快不快的过程 所以打算做异步调用 返回我所需要的结果即可 ,至于缓存什么时候更新完 就不是我所需要关注的了 废话不多说 上代码 publ ...

  3. java同步方法完成案例_Java同步代码块和同步方法原理与应用案例详解

    本文实例讲述了java同步代码块和同步方法.分享给大家供大家参考,具体如下: 一 点睛 所谓原子性WOmoad:一段代码要么执行,要么不执行,不存在执行一部分被中断的情况.言外之意是这段代码就像原子一 ...

  4. java中receive功能_java - 在onReceive()回调中的synchronized块 - SO中文参考 - www.soinside.com...

    我正在阅读this page关于如何编程Android与USB配件通信.其中一个步骤涉及注册BroadcastReceiver以获得用户的许可: IntentFilter filter = new I ...

  5. java虚拟机可以处理_Java虚拟机对类加载的处理机制

    类被加载到虚拟机内存开始,到卸载出内存为止,经历了:加载->验证->准备->解析->初始化->使用->卸载 这七个过程 加载 在加载阶段,虚拟机要完成三件事: (1 ...

  6. java 反射与泛型_Java基础系列 - 泛型和反射机制

    package com.test5; import java.lang.reflect.Field; import java.lang.reflect.Method; /** * Java泛型和反射机 ...

  7. java 类加载 双亲委派_Java类加载器和双亲委派机制

    前言 之前详细介绍了Java类的整个加载过程(类加载机制详解).虽然,篇幅较长,但是也不要被内容吓到了,其实每个阶段都可以用一句话来概括. 1)加载:查找并加载类的二进制字节流数据. 2)验证:保证被 ...

  8. java 打印预览_java打印和打印预览机制实例代码

    代码如下: import java.awt.basicstroke; import java.awt.borderlayout; import java.awt.color; import java. ...

  9. 8_gin日拱一足---异步和同步

    8_gin日拱一足---异步和同步 gin_日拱一足---异步和同步 gin_日拱一足-异步和同步 异步处理:可以方便的进行异步的处理请求-高并发场景可以使用异步请求的方式启动多个gorotine 切 ...

最新文章

  1. 每天学一点儿shell:vi和vim命令使用
  2. java query api_ElasticSearch(十二) Bool Query JAVA API
  3. Swift之深入解析协议Protocol的底层原理
  4. python 输入参数获取_python获取输入参数
  5. 火狐浏览器如何更改字体 火狐浏览器字体更改方法分享
  6. springboot jwt token前后端分离_基于Spring Boot+Spring Security+JWT+Vue前后端分离的开源项目...
  7. C++中时间相关函数的使用
  8. keras 中 reuse 问题
  9. mac废纸篓清空的心得、mac设置不睡眠不待机不锁屏、如何快速锁屏待机睡眠、mac重启、mac学习的必备软件-城...
  10. Linux SPI驱动(Linux驱动开发篇)
  11. Overfeat 笔记
  12. 在pycharm中使用pyqt5时clicked().后面connect不自动补全问题解决办法
  13. [SageMath] 关于SageMath本地环境的搭建与基本使用
  14. 移动终端开发工程师工作流程的总结
  15. T2695 桶哥的问题——吃桶
  16. XML格式文件转化为实体类Bean
  17. 如何 接收消息服务器url,(读书笔记)网络是怎样连接的——浏览器生成消息...
  18. 东风风神酷我音乐显示服务器错误,评测:东风风神奕炫GS中控屏幕多媒体系统使用说明...
  19. 数据库设计的六个阶段
  20. 大学生电子设计大赛(内容有点多,细细看看,应该会有收获)

热门文章

  1. ios和鸿蒙哪个好,鸿蒙和iOS的两大区别!看过这两大区别,网友惊叹:鸿蒙太强大了...
  2. 心然-心之所在,浮生安然
  3. CentOS7上安装MongoDB及基础命令学习
  4. 来了!阿里智能人机交互的神秘核心技术解析
  5. 查看此docker网络连接模式_Docker系列-Docker 网络模式及配置
  6. 互联网公司MySQL常用分库分表方案总结
  7. 过拟合(Over-fitting) 和 欠拟合(Under-fitting)
  8. 强制关闭一个进程TerminateProcess
  9. 排序算法-归并排序的时间复杂度分析
  10. SecureBridge Alexandria Release 2和iOS 15的支持