java调用lingo_使用Lingo增强JMS

虽然activemq+jencks的jms轻量级解决方案已经很好地在psa中work了,尤其spring的JmsTemplate使得代码更简单,但是还是存在问题。

问题来自暑期做psa的时候,linke突然提出要求,需要MDP返回些处理信息,比如处理结果、异常,以便后台监控和前台显示,但是,MDP没有返回值也没法返回异常,当时我只能无奈。

Lingo解决了这个问题,它扩展了JMS,允许异步的函数调用。

在下载了lingo-1.0-M1后(虽然1.2.1发布了,但是还没有文档支持,所以暂且用1.0),参考其自带的example,了解了它异步函数调用的代码思路。

客户端拥有服务端的方法接口,客户端将callback和相关参数代入接口,进行异步调用,而服务端的接口实现中利用callback来返回必要的信息。

callback实现了EventListener,提供了返回值和异常的接口,另外涉及到两个方面,首先,callback本身需要轮询,其次,callback可以由实例池管理。

第一个方面主要参考了lingo的example,使用semaphore来进行轮询。

第二个方面并没有利用实例池,而是利用ThreadPoolExecutor来newFixedThreadPool,管理不同的异步调用线程,来完成对callback的调度。

配置部分:

encoding="UTF-8"?>

/p>

BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

class="org.activemq.spring.BrokerFactoryBean">

value="classpath:activemq.xml"

/>

class="org.activemq.ActiveMQConnectionFactory">

name="brokerURL">

tcp://localhost:61616

class="org.activemq.message.ActiveMQQueue">

index="0">

lingo.demo

id="invocationFactory"

class="org.logicblaze.lingo.LingoRemoteInvocationFactory">

class="org.logicblaze.lingo.SimpleMetadataStrategy">

value="true" />

class="org.logicblaze.lingo.jms.JmsProxyFactoryBean">

value="org.openepo.jms.lingo.MailService"

/>

ref="jmsFactory" />

ref="destination" />

name="remoteInvocationFactory"

ref="invocationFactory" />

class="org.logicblaze.lingo.jms.JmsServiceExporter">

ref="serverImpl" />

value="org.openepo.jms.lingo.MailService"

/>

ref="jmsFactory" />

ref="destination" />

ref="invocationFactory" />

class="org.openepo.jms.lingo.MailServiceImpl"

/>

class="org.openepo.jms.lingo.AsyncManager"

singleton="false">

/>

/>

ResultListener和ResultListenerImpl:callback接口及实现。

ResultListener.java:

package org.openepo.jms.lingo;

import java.util.EventListener;

public interface ResultListener extends EventListener {

public void onResult(Object result);

// lifecycle end methods

public void stop();

public void onException(Exception e);

}

ResultListenerImpl.java:

package org.openepo.jms.lingo;

import java.util.ArrayList;

import java.util.List;

public class ResultListenerImpl implements ResultListener

{

private List results = new ArrayList();

private Object semaphore = new Object();

private boolean stopped;

private Exception onException;

private long waitTime = 1000;

public synchronized void onResult(Object result)

{

results.add(result);

synchronized (semaphore) {

semaphore.notifyAll();

}

}

// lifecycle end methods

public void stop() {

stopped = true;

}

public void onException(Exception e)

{

onException = e;

}

public Exception getOnException()

{

return

onException;

}

public List getResults()

{

return results;

}

public boolean isStopped()

{

return stopped;

}

public void waitForAsyncResponses(int

messageCount) {

System.out.println("Waiting for: " + messageCount +

" responses to arrive");

long start =

System.currentTimeMillis();

for (int i = 0; i

< 10; i++) {

try {

if (hasReceivedResponses(messageCount))

{

break;

}

synchronized (semaphore) {

semaphore.wait(waitTime);

}

}

catch (InterruptedException e) {

System.out.println("Caught: " + e);

}

}

long end =

System.currentTimeMillis() - start;

System.out.println("End of wait for " + end + " millis");

}

protected boolean hasReceivedResponse()

{

return

results.isEmpty();

}

protected synchronized boolean

hasReceivedResponses(int messageCount) {

return results.size()

>= messageCount;

}

public long getWaitTime()

{

return waitTime;

}

public void setWaitTime(long waitTime)

{

this.waitTime =

waitTime;

}

}

MailService和MailServiceImpl:服务代码。

MailService.java:

package org.openepo.jms.lingo;

import java.util.List;

public interface MailService {

public void

asyncSendMail(List mails,

ResultListener listener);

}

MailServiceImpl.java:

package org.openepo.jms.lingo;

import java.util.List;

public class MailServiceImpl implements MailService

{

public void

asyncSendMail(List mails,

ResultListener listener) {

try {

for (Mail mail : mails) {

sendMail(mail);

Thread.sleep(2000);// 服务端时耗

listener.onResult(mail.getContent() +

" Sended Successfully.");

}

listener.stop();

} catch

(Exception e) {

listener.onException(e);

}

}

public void sendMail(Mail mail) throws

Exception {

// 可以取消下面的注释来查看服务端将异常传给客户端

//throw new Exception("Error occurs

on server side.");

}

}

在服务端方法中,可以利用callback将处理结果,是否结束和异常信息返回客户端.

Mail.java:

package org.openepo.jms.lingo;

import java.io.Serializable;

public class Mail implements Serializable

{

private static final long serialVersionUID = 1L;

private String content;

public String getContent() {

return content;

}

public void setContent(String content)

{

this.content = content;

}

public Mail(String content) {

this.content = content;

}

}

AsyncManager:各类异步调用的方法可以集中在这个类中,利用线程池来统一控制callback实例。

AsyncManager.java:

package org.openepo.jms.lingo;

import java.util.List;

import java.util.concurrent.Executors;

import java.util.concurrent.ThreadPoolExecutor;

public class AsyncManager {

static private int threadSize =

10;   //callback池大小

static private ThreadPoolExecutor executor =

(ThreadPoolExecutor) Executors

.newFixedThreadPool(threadSize); //callback池

public void setThreadSize(int threadSize)

{

AsyncManager.threadSize = threadSize;

}

private MailService mailClient;

public void setMailClient(MailService mailClient)

{

this.mailClient = mailClient;

}

public AsyncManager() {

}

public void sendMails(final

List mails)

{

// callback对象

final ResultListenerImpl callBack = new

ResultListenerImpl();

callBack.setWaitTime(2000);

// 异步调用

mailClient.asyncSendMail(mails, callBack);

// 调用线程池中的callback

executor.execute(new Runnable()

{

public void run() {

// callBack 阻塞等待n个消息

callBack.waitForAsyncResponses(mails.size());

if (callBack.getOnException() != null) {

// 服务端异常

System.out.println("Server

Exception: "

+

callBack.getOnException().getMessage());

} else

{

// 得到服务端处理结果,打印结果

for (Object result :

callBack.getResults())

{

System.out.println("Result:

" + result);

}

}

}

});

}

}

上面匿名类的run方法中,在callback的waitForAsyncResponses方法结束后,可以检查callback中的信息,进行异常处理等。

下面是测试用例:

@Test

public void test() {

List mails = new

ArrayList();

mails.add(new Mail("mail1"));

mails.add(new Mail("mail2"));

// 计算时间

long startTime = System.currentTimeMillis();

try {

// 异步调用

asyncManager.sendMails(mails);

// 没有阻塞

System.out.println("Cost time "

+ (System.currentTimeMillis() -

startTime) + "ms");

//为查看结果,sleep主线程

Thread.sleep(10000);

} catch (InterruptedException e)

{

e.printStackTrace();

}

}

使用Lingo对JMS增强后,通过callback,使得异步调用的确比较OO了,但是更重要的是服务端的信息可以通过callback返回给客户端,客户端可以相应地进行处理。

多出了许多代码,自然复杂度有所增加,但是lingo-1.2.1后,增加了annotation,减少了callback的代码量。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/441383.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

jsk Star War (线段树维护区间最小最大值 + 二分)

Description 公元20XX年&#xff0c;人类与外星人之间的大战终于爆发。 现有一个人类军团&#xff0c;由n名士兵组成&#xff0c;第i个士兵的战斗力值对应一个非负整数ai (1 \leq i \leq n1≤i≤n)。 有一天&#xff0c;某个战力爆表的外星人NaN单独向地球人宣战&#xff0c…

java jsp导出pdf文件_JSP页面导出PDF格式文件

JSP页面导出PDF格式文件基本在前端页面可以全部完成添加下载链接的点击事件var downPdf document.getElementById("downLoad");downPdf.onclick function() {downPdf.parentNode.removeChild(downPdf);html2canvas(document.body, {onrendered:function(canvas) {v…

【51Nod - 1094】和为k的连续区间 (前缀和,二分查找)

题干&#xff1a; 一整数数列a1, a2, ... , an&#xff08;有正有负&#xff09;&#xff0c;以及另一个整数k&#xff0c;求一个区间i,ji,j&#xff0c;(1 < i < j < n)&#xff0c;使得aii ... ajj k。 Input 第1行&#xff1a;2个数N,K。N为数列的长度。K为需…

简述java的线程_Java多线程的简述

线程与进程进程&#xff1a;​ 是指一个内存中运行的应用程序&#xff0c;每个进程都有一个独立的内存空间&#xff0c;一个应用程序可以同时运行多个进程&#xff1b;进程也是程序的一次执行过程&#xff0c;是系统运行程序的基本单位&#xff1b;系统运行一个程序即是一个进程…

【POJ - 3253】Fence Repair(贪心,时光倒流)

题干&#xff1a; Description Farmer John wants to repair a small length of the fence around the pasture. He measures the fence and finds that he needs N (1 ≤ N ≤ 20,000) planks of wood, each having some integer length Li (1 ≤ Li ≤ 50,000) units. He t…

java unsafe park_Java中Unsafe类详解

http://www.cnblogs.com/mickole/articles/3757278.htmlJava不能直接访问操作系统底层&#xff0c;而是通过本地方法来访问。Unsafe类提供了硬件级别的原子操作&#xff0c;主要提供了以下功能&#xff1a;1、通过Unsafe类可以分配内存&#xff0c;可以释放内存&#xff1b;类中…

【CodeForces - 124D】Squares (旋转坐标系,计算几何,思维)

题干&#xff1a; You are given an infinite checkered field. You should get from a square (x1; y1) to a square (x2; y2). Using the shortest path is not necessary. You can move on the field squares in four directions. That is, when you are positioned in any…

java图形设计_java图形界面设计含答案

十一章 图形用户界面程序设计入门一&#xff0e;选择题&#xff1a;1. 容器Panel和applet缺省使用的布局编辑策略是 BA、BorderLayout B、FlowLayoutC、GridLayout D、CarLayout2. .applet类的直接父类是&#xff1a; BA、Component类 B、Container类C、Frame类 D、Panel类3. .…

【qduoj - 夏季学期创新题】骑士游历(递推dp)

题干&#xff1a; 描述 输入 输入包含多组数据&#xff0c;第一行T表示数据组数接下来每行六个整数n&#xff0c;m&#xff0c;x1&#xff0c;y1&#xff0c;x2&#xff0c;y2(分别表示n&#xff0c;m&#xff0c;起点坐标&#xff0c;终点坐标) 输出 输出T行&#xff0c;表示…

java ee 6 源码_Java EE 6开发手册·高级篇(第4版)

资源名称&#xff1a;Java EE 6开发手册高级篇(第4版)内容简介&#xff1a;《Java EE 6 开发手册?高级篇(第4 版)》是一本面向实战、以示例为驱动、在Java 平台企业版6(Java EE 6)上开发企业级应用的指南。该指南基于The Java EE 6 Tutorial: Basic Concepts&#xff0c;Fourt…

【qduoj - 夏季学期创新题】矩形剖分(递归,dp)

题干&#xff1a; 描述 对一个给定的矩形&#xff0c;将其划分成尽可能少的正方形&#xff0c;输出正方形的最少个数。例如&#xff0c;如下图所示的情况&#xff0c;则输入为3和4&#xff0c;输出为4。 输入 输入两个整数中间用空格分开。 输出 输出最少分割成的正方形的个…

java8 nio_Java8之 NIO的学习

一、什么是NIO&#xff1f;Java NIO(New IO)是从Java 1.4版本开始引入的一个新的IO API&#xff0c;可以替代标准的Java IO API。NIO与原来的IO有同样的作用和目的&#xff0c;但是使用的方式完全不同&#xff0c;NIO支持面向缓冲区的、基于通道的IO操作。NIO将以更加高效的方式…

【牛客 - 125A】灰魔法师(打表,暴力)

题干&#xff1a; 给出长度为n的序列a, 求有多少对数对 (i, j) (1 < i < j < n) 满足 ai aj 为完全平方数。 输入描述: 第一行一个整数 n (1 < n < 105) 第二行 n 个整数 ai (1 < ai < 105) 输出描述: 输出一个整数&#xff0c;表示满足上述条件的数…

学分绩点计算编程java_方便我们计算学分绩点的JavaScript

基于目前我们学校教务处的管理系统, 依靠Javascript的帮忙, 我们可以很方便地计算成绩.测试用HTML:style"width: 100%; border-collapse: collapse;">课程代码课程名称课程性质成绩补考成绩重修成绩学分绩点辅修标记24109505数据库系统实验专业基础课优秀0.54.502…

【POJ - 2663】Tri Tiling (简单dp)

题干&#xff1a; In how many ways can you tile a 3xn rectangle with 2x1 dominoes? Here is a sample tiling of a 3x12 rectangle. Input Input consists of several test cases followed by a line containing -1. Each test case is a line containing an integer …

java 反射 代码_java反射机制学习代码

根据http://www.iteye.com/topic/137944文档进行学习代码如下:package reflectTest;import java.lang.reflect.*;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.io.*;class A{}class B extends A{}class C extends B{}class TestClass …

【POJ - 1556】The Doors (计算几何,线段相交)

题干&#xff1a; You are to find the length of the shortest path through a chamber containing obstructing walls. The chamber will always have sides at x 0, x 10, y 0, and y 10. The initial and final points of the path are always (0, 5) and (10, 5). Th…

java处理linux中的 m_Linux下处理BOM头和^M的简单方法

Linux在网络服务器、嵌入式设备的市场上占有较大份额&#xff0c;Microsoft Windows在桌面操作系统上占有较大的份额&#xff0c;因此有很多的人喜欢用Windows去控制操作Linux。既然用Windows去控制Linux&#xff0c;难免导致Windows系统上的产生的文件以某种途径传到了Linux系…

【POJ - 1696】Space Ant (凸包,最小极角,排序)

题干&#xff1a; The most exciting space discovery occurred at the end of the 20th century. In 1999, scientists traced down an ant-like creature in the planet Y1999 and called it M11. It has only one eye on the left side of its head and just three feet al…

2019蓝桥杯Java决赛题答案_2019第十届蓝桥杯JavaB组省赛真题详解

目录题解待更新第一题&#xff1a;组队题目描述做为篮球队教练&#xff0c;你须要从如下名单中选出 1 号位至 5 号位各一名球员&#xff0c; 组成球队的首发阵容。每位球员担任 1 号位至 5 号位时的评分以下表所示。请你计算首发阵容 1 号位至 5 号位的评分之和最大多是多少&am…