jms异步转同步调用实例

思路:

当主线程调用异步方法时,将自己挂起,并把引用交给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返回的消息可能会在其他主机上,则当前主机的主线程无法唤醒,并且另一个主机也会有问题(找不到主线程)

posted @ 2013-11-06 16:01  嗨,你的益达~~~  阅读(851)  评论(0编辑  收藏  举报