在JAVA平台,实现异步调用的角色有如下三个角色:
 
调用者 取货凭证   真实数据
 
一个调用者在调用耗时操作,不能立即返回数据时,先返回一个取货凭证.然后在过一断时间后凭取货凭证来获取真正的数据.
 

所以连结调用者和真实数据之间的桥梁是取货凭证.我们先来看它的实现:

public class FutureTicket{
 private Object data = null;
 private boolean completed = false;

 public synchronized void makeRealData(){
  if(this.complited) return;
  //获取数据的耗时操作.这里用Sleep代替
  try{
   Thread.sleep(10000);
  }catch(Throwable t){}
  this.data = "返回的数据内容";
  this.completed = true;
  notifyAll();
 }

 public synchronized Object getData(){
  while(!this.completed)){
   try{
    wait();
   }catch(Throwable t){}
  }
  return this.data;

 }
 public boolean isCompleted(){
  return this.completed;
 }
}

为了简单化说明(不把它们的关系开得复杂),这里用Objectb代替了真实数据.而真实的实现中我们应该把makeData放在一个真实数据的类中,然后提供一个方法返回真实数据.这样对于真实数据的处理和取货凭证解耦.
 
对于这个取货凭证,调用者的如何调用是异步调用的关键:

publc class Requester{
 public FutureTicket request(){
  final FutureTicket ft = new FutureTicket();

  //在新线程中调用耗时操作
  new Thread(){
   public void run(){
    ft.makeRealData();
   }
  }.start();
  return ft;
 }
}

在新线程中启动耗时操作后,不等待线程的完成立即返回提货单.
 
然后调用者可以根据ft.isCompleted()来调用getData()获取真实数据.当然对ft.isCompleted()测试可以按规定时间间隔轮巡(极低级的方案),也可以在条件不满足时wait(),然后等待makeData的notifyAll();这样你就完成了一个用JAVA模拟的异步操作.
 

改进:
但这样的调用对于调用者来说仍然要继续控制线程操作.如果调用者是一个资深的程序员,这当然没有问题.但假如我们把对直接数据的处理委托给取货凭证来做.调用者直接规定对数据的操作,然后由取货凭证来调用规定的操作,这对于调用者是一个很好的解脱:

interface ProcessData{
 public void process(Onject data);
}

public MyProcessData{
 public void process(Object data){
  //你不管什么时候起初数据data被获取了.
  //你只要规定如果获取到数据了如何处理

  System.out.println(data.toString() + "处理完成...........");
  //insert into dataBase?
 }
}

取货凭证在接收调用者请求获取数据时,要知道对获取的数据如何处理的方法:

public class FutureTicket{
 private Object data = null;
 private boolean completed = false;
 private ProcessData pd;

 public FutureTicket(ProcessData pd){
  this.pd = pd;
 }
 public synchronized void makeRealData(ProcessData pd){
  if(this.complited) return;
  //获取数据的耗时操作.这里用Sleep代替
  try{
   Thread.sleep(10000);
  }catch(Throwable t){}
  this.data = "返回的数据内容";
  this.completed = true;
  notifyAll();
 }

 public synchronized void putData(){
  while(!this.completed)){
   try{
    wait();
   }catch(Throwable t){}
  }
  //return this.data;
  //不用返回了,直接处理
  this.pd.process(this.data);
  // alert(?);

 }

 //这个方法也可以不要了.
 public boolean isCompleted(){
  return this.completed;
 }
}

调用:

  final FutureTicket ft = new FutureTicket(new ProcessData());

  //在新线程中调用耗时操作
  new Thread(){
   public void run(){
    ft.makeRealData();
   }
  }.start();
  ft.putData();

OK,你现在可以抽烟,喝酒,泡妞.ft会为你完成所有的工作.

java实现异步调用实例的更多相关文章

  1. 利用回调实现Java的异步调用

    异步是指调用发出后,调用者不会立刻得到结果,而是在调用发出后,被调用者通知调用者,或通过回调函数处理这个调用. 回调简单地说就是B中有一个A,这样A在调用B的某个方法时实际上是调用到了自己的方法. 利 ...

  2. .NET中的async和await关键字使用及Task异步调用实例

    其实早在.NET 4.5的时候M$就在.NET中引入了async和await关键字(VB为Async和Await)来简化异步调用的编程模式.我也早就体验过了,现在写一篇日志来记录一下顺便凑日志数量(以 ...

  3. C#_delegate - 异步调用实例 BeginInvoke EndInvoke event

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  4. Java 实现异步调用

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

  5. 功能完善的Java连接池调用实例

    /** * Title: ConnectPool.java * Description: 连接池管理器 * Copyright: Copyright © 2002/12/25 * Company: * ...

  6. java中异步调用注意

    Future接口是Java标准API的一部分,在java.util.concurrent包中.Future接口是Java线程Future模式的实现,可以来进行异步计算. 有了Future就可以进行三段 ...

  7. Java实现异步调用

    一.创建线程 @Test public void test0() throws Exception { System.out.println("main函数开始执行"); Thre ...

  8. java中异步调用的解决方法

    package demo.future; import java.util.ArrayList; import java.util.List; import java.util.concurrent. ...

  9. 5种必会的Java异步调用转同步的方法你会几种

    转载请注明本文地址:https://www.jianshu.com/p/f00aa6f66281 源码地址:https://gitee.com/sunnymore/asyncToSync Sunny先 ...

随机推荐

  1. 安装ipython,使用scrapy shell来验证xpath选择的结果 | How to install iPython and how does it work with Scrapy Shell

    1. scrapy shell 是scrapy包的一个很好的交互性工具,目前我使用它主要用于验证xpath选择的结果.安装好了scrapy之后,就能够直接在cmd上操作scrapy shell了. 具 ...

  2. C++值传递与引用传递

    值传递:形参是对实参的拷贝,改变形参的值不会改变外部实参的值,从被调用的角度来说,值传递时单向传递(实参->形参),参数的值只能传入,不能传出. 当函数内部需要修改参数,并且不希望这个改变影响调 ...

  3. C语言程序设计第五次作业——循环结构1

    (一)改错题 输出华氏摄氏温度转换表:输入两个整数lower和upper,输出一张华氏摄氏温度转换表,华氏温度的取值范围是{lower,upper},每次增加2℉.计算公式如下: c = 5×(f-3 ...

  4. C语言程序第三次作业

    (一)改错题 计算f(x)的值:输入实数x,计算并输出下列分段函数f(x)的值,输出时保留1位小数. 输入输出样例1: Enterr x: 10.0 f(10.0) = 0.1 输入输出样例2: En ...

  5. Oracle中备份用户对象的两种方法

    方法1: 执行步骤: exp userid=用户名/密码@数据库名 file=c:\emp.dmp 使用当前用户导出 exp userid=sys/sys@数据库名 file=c:\emp.dmp o ...

  6. Java关键字---this的由来和其三大作用

    [声明]欢迎转载,但请保留文章原始出处→_→ 秦学苦练:http://www.cnblogs.com/Qinstudy/ 文章来源:http://www.cnblogs.com/Qinstudy/p/ ...

  7. Java面试18|关于进程、线程与协程

    1.IPC(Inter-Process Communication,进程间通信)与线程通信的几种方式 # 管道( pipe ):管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进 ...

  8. JavaScript for 循环

    循环可以将代码块执行指定的次数. JavaScript 循环 如果您希望一遍又一遍地运行相同的代码,并且每次的值都不同,那么使用循环是很方便的. 我们可以这样输出数组的值: 一般写法: documen ...

  9. Ruby方法参数默认值的一个小技巧在Rails中的应用

    我们需要生成一个gravatar格式的html.image标示,于是写了如下方法: def gravatar_for(user) gravatar_id = Digest::MD5::hexdiges ...

  10. synchronized与条件同步

    在并发编程中,有这样的需求:当满足某个条件时线程执行同步块中的代码,条件不满足时,让线程在此等待,直至条件满足再执行同步代码块. java的Object类即提供了一类这样的方法wait(),notif ...