`
javaG
  • 浏览: 554571 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

Java 异步消息处理

阅读更多

Java 异步消息处理

       在前一节实现异步调用的基础上 , 现在我们来看一下一个完善的 Java 异步消息处理机制 .

[ 写在本节之前 ]

       在所有这些地方 , 我始终没有提到设计模式这个词 , 而事实上 , 多线程编程几乎每一步都在应该设计模式 . 你只要能恰如其份地应用它 , 为什么要在意你用了某某名称的模式呢 ?

       一个说书人它可以把武功招数说得天花乱坠 , 引得一班听书客掌声如雷 , 但他只是说书的 . 真正的武林高手也许并不知道自己的招式在说书人口中叫什么 , 这不重要 , 重要的是他能在最恰当的时机把他不知名的招式发挥到极致 !

       你了解再多的设计模式 , 或你写出了此类的著作 , 并不重要 , 重要的是你能应用它设计出性能卓越的系统 .

 

 

       本节的这个例子 , 如果你真正的理解了 , 不要怀疑自己 , 你已经是 Java 高手的行列了 . 如果你抛开本节的内容 , 五天后能自己独立地把它再实现一次 , 那你完全可以不用再看我写的文章系列了 , 至少是目前 , 我再也没有更高级的内容要介绍了 .

       上节的 Java 异步调用为了简化调用关系 , 很多角色被合并到一个类中实现 , 为了帮助大家改快地抓住核心的流程 . 那么一个真正的异步消息处理器 , 当然不是这样的简单 .

一.    它要能适应不同类型的请求 :

本节用 makeString 来说明要求有返回值的请求 . displayString 来说明不需要返回值的请求 .

二.    要能同时并发处理多个请求 , 并能按一定机制调度 :

本节将用一个队列来存放请求 , 所以只能按 FIFO 机制调度 , 你可以改用 LinkedList, 就可以简单实现一个优先级 ( 优先级高的 addFirst, 低的 addLast).

三.    有能力将调用的边界从线程扩展到机器间 (RMI)

四.    分离过度耦合 , 如分离调用句柄 ( 取货凭证 ) 和真实数据的实现 . 分离调用和执行的过程 , 可以尽快地将调返回 .

 

现在看具体的实现 :

public interface Axman {

  Result resultTest(int count,char c);

  void noResultTest(String str);

}

这个接口有两个方法要实现 , 就是有返回值的调用 resultTest 和不需要返回值的调用

noResultTest, 我们把这个接口用一个代理类来实现 , 目的是将方法调用转化为对象 , 这样就可以将多个请求 ( 多个方法调 ) 放到一个容器中缓存起来 , 然后统一处理 , 因为 Java 不支持方法指针 , 所以把方法调用转换为对象 , 然后在这个对象上统一执行它们的方法 , 不仅可以做到异步处理 , 而且可以将代表方法调用的请求对象序列化后通过网络传递到另一个机器上执行 (RMI). 这也是 Java 回调机制最有力的实现 .

       一个简单的例子 .

       如果 1: A

       如果 2: B

如果 3: C

如果有 1000 个情况 , 你不至于用 1000 case ? 以后再增加呢 ?

所以如果 C/C++ 程序员 , 会这样实现 : (c c++ 定义结构不同 )

 

type define struct MyStruct{

int mark;

(*fn) ();

} MyList;

      

       然后你可以声明这个结构数据 :

       {1,A,

         2,B

         3,C

}

做一个循环 :

for(i=0;i<length;i++) {

       if( 数据组 [i].mark == 传入的值 ) ( 数据组 [i].*fn)();

}

简单说 c/c++ 中将要被调用的涵数可以被保存起来 , 然后去访问 , 调用 , Java , 我们无法将一个方法保存 , 除了直接调用 , 所以将要调用的方法用子类来实现 , 然后把这些子类实例保存起来 , 然后在这些子类的实现上调用方法 :

interface My{

       void test();

}

 

class A implements My{

       public void test(){

              System.out.println(“A”):

}

}

class B implements My{

       public void test(){

              System.out.println(“B”):

}

}

 

class C implements My{

       public void test(){

              System.out.println(“C”):

}

}

 

class MyStruct {

      

       int mark;

       My m;

       public MyStruct(int mark,My m){this.mark = amrk;this.m = m}

}

数组 :

{ new MyStruct(1,new A()),new MyStruct(2,new B()),new MyStruct(3,new C())}

for(xxxxxxxxx) if( 参数 == 数组 [i].mark) 数组 [i].m.test();

 

这样把要调用的方法转换为对象的保程不仅仅是可以对要调用的方法进行调度 , 而且可以把对象序列化后在另一台机器上执行 , 这样就把调用边界从线程扩展到了机器 .

 

回到我们的例子 :

class Proxy implements Axman{

  private final Scheduler scheduler;

  private final Servant servant;

 

  public Proxy(Scheduler scheduler,Servant servant){

    this.scheduler = scheduler;

    this.servant = servant;

  }

  public Result resultTest(int count,char c){

    FutureResult futrue = new FutureResult();

    this.scheduler.invoke(new ResultRequest(servant,futrue,count,c));

    return futrue;

  }

 

  public void noResultTest(String str){

    this.scheduler.invoke(new NoResultRequest(this.servant,str));

  }

}

 

其中 scheduler 是管理对调用的调度 , servant 是真正的对方法的执行 :

 

Servant 就是去真实地实现方法 :

 

class Servant implements Axman{

  public Result resultTest(int count,char c){

    char[] buf = new char[count];

    for(int i = 0;i < count;i++){

      buf[i] = c;

      try{

        Thread.sleep(100);

      }catch(Throwable t){}

    }

    return new RealResult(new String(buf));

  }

 

  public void noResultTest(String str){

    try{

      System.out.println("displayString :" + str);

      Thread.sleep(10);

    }catch(Throwable t){}

  }

}

scheduler 将方法的调用 (invkoe) 和执行 (execute) 进行了分离 , 调用就是开始 注册 方法到要执行的容器中 , 这样就可以立即返回出来 . 真正执行多久就是 execute 的事了 , 就象一个人点燃爆竹的引信就跑了 , 至于那个爆竹什么时候爆炸就不是他能控制的了 .

public class Scheduler extends Thread {

  private final ActivationQueue queue;

  public Scheduler(ActivationQueue queue){

    this.queue = queue;

  }

 

  public void invoke(MethodRequest request){

    this.queue.putRequest(request);

  }

 

  public void run(){

    while(true){

 

      // 如果队列中有请求线程 , 测开始执行请求

      MethodRequest request = this.queue.takeRequest();

      request.execute();

    }

  }

}

scheduler 中只用一个队列来保存代表方法和请求对象 , 实行简单的 FIFO 调用 , 你要实更复杂的调度就要在这里重新实现 :

class ActivationQueue{

  private static final int MAX_METHOD_REQUEST = 100;

  private final MethodRequest[] requestQueue;

  private int tail;

  private int head;

  private int count;

 

  public ActivationQueue(){

    this.requestQueue = new MethodRequest[MAX_METHOD_REQUEST];

    this.head = this.count = this.tail = 0;

  }

 

  public synchronized void putRequest(MethodRequest request){

    while(this.count >= this.requestQueue.length){

      try {

        this.wait();

      }

      catch (Throwable t) {}

    }

    this.requestQueue[this.tail] = request;

    tail = (tail + 1)%this.requestQueue.length;

    count ++ ;

    this.notifyAll();

 

  }

 

 

  public synchronized MethodRequest takeRequest(){

    while(this.count <= 0){

      try {

        this.wait();

      }

      catch (Throwable t) {}

 

    }

 

    MethodRequest request = this.requestQueue[this.head];

    this.head = (this.head + 1) % this.requestQueue.length;

    count --;

    this.notifyAll();

    return request;

  }

}

 

为了将方法调用转化为对象 , 我们通过实现 MethodRequest 对象的 execute 方法来方法具体方法转换成具体对象 :

abstract class MethodRequest{

  protected final Servant servant;

分享到:
评论
1 楼 uuu999ggg 2012-03-06  
好像没写全啊。。。

相关推荐

    MongoDB分片集群搭建教程:副本集创建与数据分片

    内容概要:本文提供了详细的MongoDB分片集群的搭建指导,涵盖了从环境准备、配置文件编写、副本集的建立、主节点的选择、配置服务器和数据分片服务器的配置到最后的路由节点的搭建与操作整个流程,以及对数据库的哈希与范围两种分片策略的应用介绍和具体命令执行。 适合人群:熟悉NoSQL数据库概念并对MongoDB有一定了解的技术人员,尤其是在大型数据管理和分布式数据库架构设计中有需求的开发者。 使用场景及目标:帮助技术人员掌握构建高效能、高可用性的MongoDB分片集群的方法,适用于处理大规模、实时性强的数据存储与读取场景。 其他说明:文中通过实例演示了每个步骤的具体操作方法,便于跟随文档实操,同时也介绍了可能遇到的问题及其解决方案,如在没有正确配置的情况下试图写入数据时出现错误等情况的处理。

    CPPC++_嵌入式硬件的物联网解决方案blinker库与Arduino ESP8266 ESP32一起工作.zip

    CPPC++_嵌入式硬件的物联网解决方案blinker库与Arduino ESP8266 ESP32一起工作

    CPPC++_逆向调用QQ Mojo IPC与WeChat XPlugin.zip

    CPPC++_逆向调用QQ Mojo IPC与WeChat XPlugin

    CPPC++_现代活动指标.zip

    CPPC++_现代活动指标

    CPPC++_Xournal是一款手写笔记软件,支持PDF注释,使用C语言编写,支持GTK3,支持Linux,如Ubu.zip

    CPPC++_Xournal是一款手写笔记软件,支持PDF注释,使用C语言编写,支持GTK3,支持Linux,如Ubu

    基于SSM学生实习管理系统前台小程序与后台管理系统开发实践

    资源概述: 本资源提供了一套完整的学生实习管理系统解决方案,涵盖了前台小程序页面与后台管理系统两大模块。前台小程序页面设计简洁直观,用户可根据不同身份(学生或企业)进行登录。学生用户能够方便地浏览并投递感兴趣的实习岗位,而企业用户则能轻松发布实习信息,吸引优秀人才。后台管理系统功能全面,包括个人中心、首页、学生管理、教师管理、企业管理、招聘管理、评分管理以及实习管理等多个方面,为管理员提供了强大的数据管理和操作工具。 技术栈亮点: SSM框架:系统后台采用Spring、Spring MVC和MyBatis Plus(简称SSM)作为核心开发框架,确保了系统的稳定性、可扩展性和可维护性。Spring作为控制反转(IoC)和面向切面编程(AOP)的容器,为系统提供了强大的业务逻辑处理能力;Spring MVC则负责处理Web请求和响应,实现了前后端的分离;MyBatis Plus作为持久层框架,简化了数据库操作,提高了开发效率。 MySQL数据库:系统采用MySQL作为数据库存储解决方案,支持大数据量的存储和高效查询。 如有侵权请联系我删除,谢谢

    微服务闪聚支付项目.zip

    微服务闪聚支付项目

    Rust 与 Java 互调实战示例

    博客链接 https://blog.csdn.net/weixin_47560078/article/details/143714557 文章从原理介绍出发,实现了 Rust 与 Java 的互调。利用 JNI 技术,可以充分发挥 Rust 的性能优势,同时保持 Java 的跨平台特性。这种技术组合适用于对性能要求较高的应用场景,如图像处理、数据分析和系统级编程等。

    CPPC++_这是我翻译的艾根中文文档.zip

    cppc++

    Matlab实现斑马优化算法ZOA-TCN-Multihead-Attention多输入单输出回归预测算法研究.rar

    1.版本:matlab2014/2019a/2024a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。 替换数据可以直接使用,注释清楚,适合新手

    Matlab实现雪融优化算法SAO-TCN-Multihead-Attention多输入单输出回归预测算法研究.rar

    1.版本:matlab2014/2019a/2024a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。 替换数据可以直接使用,注释清楚,适合新手

    分布式事务lcn.zip

    分布式事务lcn

    基于Simulink的正弦波PWM技术和三次谐波注入PWM技术研究.rar

    1.版本:matlab2014/2019a/2024a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。

    【风电功率预测】基于BiTCN的风电功率多变量输入预测研究附Matlab代码.rar

    1.版本:matlab2014/2019a/2024a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。

    CPPC++_这是由一块迷你带OV2640双DRV8833驱动TypeC接口PSRAM的ESP32PicoD4开发板驱.zip

    cppc++

    JAVA安卓手机与电脑的socket通信源码数据库 其他源码类型 WinForm

    安卓手机与电脑的socket通信源码

    Anaconda:JupyterNotebook使用教程.docx

    Anaconda:JupyterNotebook使用教程.docx

    Amazon S3:S3静态网站托管教程.docx

    Amazon S3:S3静态网站托管教程.docx

    Python商品销售数据分析可视化项目源码(期末大作业).zip

    Python商品销售数据分析可视化项目源码(期末大作业).zip,个人经导师指导并认可通过的98分大作业设计项目。主要针对计算机相关专业的正在做期末大作业设计的学生和需要项目实战练习的学习者,可作为课程设计、期末大作业,代码资料完整下载可用。 Python商品销售数据分析可视化项目源码(期末大作业).zip,个人经导师指导并认可通过的98分大作业设计项目。主要针对计算机相关专业的正在做期末大作业设计的学生和需要项目实战练习的学习者,可作为课程设计、期末大作业,代码资料完整下载可用。Python商品销售数据分析可视化项目源码(期末大作业).zip,个人经导师指导并认可通过的98分大作业设计项目。主要针对计算机相关专业的正在做期末大作业设计的学生和需要项目实战练习的学习者,可作为课程设计、期末大作业,代码资料完整下载可用。Python商品销售数据分析可视化项目源码(期末大作业).zip,个人经导师指导并认可通过的98分大作业设计项目。主要针对计算机相关专业的正在做期末大作业设计的学生和需要项目实战练习的学习者,可作为课程设计、期末大作业,代码资料完整下载可用。Python商品销售数据分析

    CPPC++_wechathookWeChatApi微信Api微信hook微信接口python微信接口java微信Ap.zip

    CPPC++_wechathookWeChatApi微信Api微信hook微信接口python微信接口java微信Ap

Global site tag (gtag.js) - Google Analytics