思路:

当主线程调用异步方法时,将自己挂起,并把引用交给jms的监听;

当监听收到返回的消息时,处理并唤醒主线程继续执行(可以获取和处理返回的消息)

Test.java

package com.my.test;

public class Test {

@org.junit.Test

public void testMain() throws InterruptedException {

new Main().main();

}

public static void main(String[] args) throws InterruptedException {

new Main().main();

}

}

Main.java

package com.my.test;

public class Main {

/**

* @param args

* @throws InterruptedException

*/

public void main() throws InterruptedException {

System.out.println("发送异步请求...");

// 发送异步请求,使用uuid作为业务标志(由客户端xml传递)

String requestXml = "...<nsrsbh>a</nsrsbh><lsh>db348708ebe46648a1c24ea5d98bc16</lsh>...";

// 解析获取流水号uuid

String uuid = getUuid(requestXml);

JMSMessageMDB ls = new JMSMessageMDB();

// 以流水号作为key,存放主线程对象

ls.putMap(uuid, this);

Thread th = new Thread(ls);

th.start();

// 传递当前实例引用,开始等待,设置超时,n秒内不返回,自己恢复

System.out.println("开始等待...");

synchronized (this) {

this.wait(10 * 60 * 1000);

}

// 异步处理后,开始继续执行,如:取异步处理的值

System.out.println("主线程开始继续执行...");

// 获取数据库的消息:根据流水号和业务类别获取

String dbMsg = Dao.getMessage(uuid);

System.out.println("获取数据库的消息:" + dbMsg);

}

// 模拟解析并获取流水号

private String getUuid(String mesage) {

return mesage.substring(mesage.indexOf("<lsh>") + 5,

mesage.indexOf("</lsh>"));

}

}

JMSMessageMDB.java

package com.my.test;

import java.util.HashMap;

import java.util.Map;

import java.util.Random;

public class JMSMessageMDB implements Runnable {

// 存放主线程对象,key为流水号,value为线程对象

private static Map<Object, Object> map = new HashMap<Object, Object>();

/**

* 这里模拟异步消息返回

*/

@Override

public void run() {

while (true) {

try {

// 监听异步消息

onMessage(createJmsMsg());

System.out.println("sleep...");

Thread.sleep(1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

/**

* 模拟异步消息返回:告诉主线程异步消息已经到来,可以去取了。

* 详细:每过来一个消息,都会根据消息的流水号从map中查找主线程对象,进而通知主线程恢复(notify);

* 消息以流水号作为主键存储在数据库中,由主线程去取;

*

* @param message

*/

public void onMessage(String message) {

// 解析消息获取流水号

String uuid = getUuid(message);

// 将消息存库(以流水号作为主键,并保存业务类别)

Dao.saveMessage(message);

// 通知主线程:

Object main = map.get(uuid);

if (null != main) {

synchronized (main) {

System.out.println("notify()");

main.notify();

}

// 清除map中此流水号(或者由主线程清除)

map.remove(uuid);

}

}

public Object getMap(Object key) {

return map.get(key);

}

public void removeMap(Object key) {

map.remove(key);

}

public void putMap(Object key, Object value) {

map.put(key, value);

}

/**

* 模拟解析并获取流水号:

* ...<nsrsbh>a</nsrsbh><lsh>db348708ebe46648a1c24ea5d98bc16</lsh>...

*

* @param mesage

* @return

*/

private String getUuid(String mesage) {

return mesage.substring(mesage.indexOf("<lsh>") + 5,

mesage.indexOf("</lsh>"));

}

private String createJmsMsg() {

String msg0 = "...<nsrsbh>a</nsrsbh><lsh>db348708ebe46648a1c24ea5d98bc10</lsh>...";

String msg1 = "...<nsrsbh>b</nsrsbh><lsh>db348708ebe46648a1c24ea5d98bc12</lsh>...";

String msg2 = "...<nsrsbh>c</nsrsbh><lsh>db348708ebe46648a1c24ea5d98bc16</lsh>...";

String msg3 = "...<nsrsbh>d</nsrsbh><lsh>db348708ebe46648a1c24ea5d98bc1w</lsh>...";

String msg4 = "...<nsrsbh>e</nsrsbh><lsh>db348708ebe46648a1c24ea5d98bc1q</lsh>...";

String[] msgs = { msg0, msg1, msg2, msg3, msg4 };

return msgs[new Random().nextInt(5)];

}

}

Dao.java

package com.my.test;

public class Dao {

public static void saveMessage(String message) {

System.out.println("save!");

}

public static String getMessage(String key) {

System.out.println("get message!");

return "Db message";

}

}

备注:

如果是集群部署,jms返回的消息可能会在其他主机上,则当前主机的主线程无法唤醒,并且另一个主机也会有问题(找不到主线程)

jms异步转同步调用实例的更多相关文章

  1. dubbo同步调用、异步调用和是否返回结果源码分析和实例

    0. dubbo同步调用.异步调用和是否返回结果配置 (1)dubbo默认为同步调用,并且有返回结果. (2)dubbo异步调用配置,设置 async="true",异步调用可以提 ...

  2. 循序渐进做项目系列(2):最简单的C/S程序——消息异步调用与消息同步调用

    上篇博客 循序渐进做项目系列(1):最简单的C/S程序——让服务器来做加法 实现了一个最简单的C/S程序,即让服务器来做加法.当时为了通俗易懂采用了消息异步调用的方式.今天我们要采用消息同步调用的方式 ...

  3. java三种调用方式(同步调用/回调/异步调用)

    1:同步调用:一种阻塞式调用,调用方要等待对方执行完毕才返回,它是一种单向调用 2:回调:一种双向调用模式,也就是说,被调用方在接口被调用时也会调用对方的接口: 3:异步调用:一种类似消息或事件的机制 ...

  4. 使用 ActiveMQ 实现JMS 异步调用

    目录 简介 启动 ActiveMQ 服务器 查看控制台 ActiveMQ 的消息通道 Queue Topic 比较 开发生产者和消费者 开发服务端(消费者) 开发客户端(生产者) 参考 简介 服务之间 ...

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

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

  6. 委托(delegate)的三种调用方式:同步调用,异步调用,异步回调(转载)

    下面为即将被调用的方法: public delegate int AddHandler(int a,int b); public class 加法类 { public static int Add(i ...

  7. C#“同步调用”、“异步调用”、“异步回调”

    本文将主要通过“同步调用”.“异步调用”.“异步回调”三个示例来讲解在用委托执行同一个“加法类”的时候的的区别和利弊. 首先,通过代码定义一个委托和下面三个示例将要调用的方法: ); //模拟该方法运 ...

  8. 整理 C#(同步调用、异步调用、异步回调)

    //闲来无事,巩固同步异步方面的知识,以备后用,特整理如下: class Program { static void Main(string[] args) { //同步调用 会阻塞当前线程,一步一步 ...

  9. C# 委托的三种调用示例(同步调用 异步调用 异步回调)

    首先,通过代码定义一个委托和下面三个示例将要调用的方法: 复制代码 代码如下: public delegate int AddHandler(int a,int b);    public class ...

随机推荐

  1. 电脑的fn锁,f1-f12与功能键 互换

    提要: 有些机子特别逆天,比如说Thinkpad e系列.好好的f1-f12一定要加上fn才能按出来,默认的是画在上面的功能键,作为娱乐来说其实是还不错的,但是像我等程序员就觉得特别逆天了.你有两个选 ...

  2. 树莓派中GPIO针角定义图

    一.上图 二.上图

  3. Payment相关逻辑

    payment相关逻辑 付款有手动付款和计划程序自动付款两种,照例先列出涉及到的概念 付款方式 - PaymentTypes - 现金,支票,信用卡,等等 记账类型 - Ledger_AccTrans ...

  4. intellij 创建测试

    之后再test目录下面创建java的文件夹,悲催的发现不能创建.想了好久,之后找到再本机的目录,手动创建java文件夹,然后点击test文件夹 ,并且点击下面的Tests文件夹 设置完test-> ...

  5. 三分钟彻底禁用、隐藏Android设备底部虚拟按钮(亲测有效)

       转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/7613970.html Android设备屏幕底部一般都有虚拟导航栏,上面有 back.home等按钮. ...

  6. Python学习笔记八:ORM框架SQLAlchemy

    一:SQLAlchemy使用 1:实体类的创建 ORM中的实体类与一般的Python类不同,在其中,使用 __tablename__=""指明该类与数据库中某个表相对应,然后定义一 ...

  7. 【Linux】eclipse juno 边框过大的调整方法

    切换至eclipse目录: vi plugins/org.eclipse.platform_4.2.*/css/e4_default_gtk.css 找到.MPartStack,替换成如下代码: .M ...

  8. java while循环语句

    //循环语句 //符合条件,循环继续执行,否则循环退出. //特点: //先判断,后执行 public class Test16{ public static void main(String arg ...

  9. jenkins相关默认路径

    安装完成后,有如下相关目录:(1)/usr/lib/jenkins/:jenkins安装目录,WAR包会放在这里.( 2 ) /etc/sysconfig/jenkins:jenkins配置文件,“端 ...

  10. loadrunner 脚本开发-参数化之将内容保存为参数、参数数组及参数值获取

    转自:http://blog.sina.com.cn/s/blog_13cc013b50102v49c.html(查看原文) 在VuGen中默认使用{}的字符串称为参数 注意:参数必须在双引号中才能用 ...