ActiveMQ使用线程池实现消息的生产与消费



spring3.1jar,以及

项目src路径下文件:config.properties

读取config.properties文件JAVA类:

package com.lejob.lejobmy.config;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

public class Configuration
{
private Properties propertie;
private FileOutputStream outputFile;

/**
* 初始化Configuration类
*/
public Configuration()
{
propertie = new Properties();
}

/**
* 初始化Configuration类
* @param filePath 要读取的配置文件的路径+名称
*/
public Configuration(String filePath)
{
propertie = new Properties();
try {
InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(filePath);
propertie.load(inputStream);
inputStream.close();
} catch (FileNotFoundException ex) {
System.out.println("读取属性文件--->失败!- 原因:文件路径错误或者文件不存在");
ex.printStackTrace();
} catch (IOException ex) {
System.out.println("装载文件--->失败!");
ex.printStackTrace();
}
}//end ReadConfigInfo(...)

/**
* 重载函数,得到key的值
* @param key 取得其值的键
* @return key的值
*/
public String getValue(String key)
{
if(propertie.containsKey(key)){
String value = propertie.getProperty(key);//得到某一属性的值
return value;
}
else 
return "";
}//end getValue(...)

/**
* 重载函数,得到key的值
* @param fileName properties文件的路径+文件名
* @param key 取得其值的键
* @return key的值
*/
public String getValue(String fileName, String key)
{
try {
String value = "";
InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(fileName);
propertie.load(inputStream);
inputStream.close();
if(propertie.containsKey(key)){
value = propertie.getProperty(key);
return value;
}else
return value;
} catch (FileNotFoundException e) {
e.printStackTrace();
return "";
} catch (IOException e) {
e.printStackTrace();
return "";
} catch (Exception ex) {
ex.printStackTrace();
return "";
}
}//end getValue(...)

/**
* 清除properties文件中所有的key和其值
*/
public void clear()
{
propertie.clear();
}//end clear();

/**
* 改变或添加一个key的值,当key存在于properties文件中时该key的值被value所代替,
* 当key不存在时,该key的值是value
* @param key 要存入的键
* @param value 要存入的值
*/
public void setValue(String key, String value)
{
propertie.setProperty(key, value);
}//end setValue(...)

/**
* 将更改后的文件数据存入指定的文件中,该文件可以事先不存在。
* @param fileName 文件路径+文件名称
* @param description 对该文件的描述
*/
public void saveFile(String fileName, String description)
{
try {
outputFile = new FileOutputStream(fileName);
propertie.store(outputFile, description);
outputFile.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException ioe){
ioe.printStackTrace();
}
}//end saveFile(...)

public static void main(String[] args)
{
Configuration rc = new Configuration("config.properties");//相对路径
String ip = rc.getValue("activemq_url");//以下读取properties文件的值
String host = rc.getValue("activemq_user");
String tab = rc.getValue("activemq_pw");
//以下输出properties读出的值
System.out.println("ip = " + ip);
System.out.println("host = " + host);
System.out.println("tab = " + tab);

// Configuration cf = new Configuration();
// String ipp = cf.getValue("./config/test.properties", "ip");
// System.out.println("ipp = " + ipp);
// cf.clear();
// cf.setValue("min", "999");
// cf.setValue("max", "1000");
// cf.saveFile("./config/save.perperties", "test");

// Configuration saveCf = new Configuration();
// saveCf.setValue("min", "10");
// saveCf.setValue("max", "1000");
// saveCf.saveFile("./config/save.perperties");

}

}

ActiveMQ消息生产者工厂类ActivemqConnectionFactory.java:

package com.lejob.lejobsearch.index.queue;

import java.io.Serializable;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import javax.jms.Connection;
import javax.jms.DeliveryMode;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MapMessage;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.ObjectMessage;
import javax.jms.Session;
import javax.jms.TextMessage;

import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.pool.PooledConnectionFactory;
import org.apache.log4j.Logger;

import com.lejob.rpc.search.model.QueueModel;


public class ActivemqConnectionFactory {
private static Logger logger = Logger.getLogger(ActivemqConnectionFactory.class);


//设置连接的最大连接数 
private static int maxConnections = 5; 
//设置每个连接中使用的最大活动会话数 
private static int maximumActiveSessionPerConnection = 300; 
//线程池数量 
private static int threadPoolSize = 50; 
//强制使用同步返回数据的格式 
private static boolean useAsyncSendForJMS = true; 

private static ExecutorService threadPool; 

private static PooledConnectionFactory connectionFactory; 


public void init(){
try {
//设置JAVA线程池 
threadPool = Executors.newFixedThreadPool(threadPoolSize); 
//ActiveMQ的连接工厂 
ActiveMQConnectionFactory actualConnectionFactory = new ActiveMQConnectionFactory(ActiveMQConstant.ACTIVEMQ_USER_NAME, ActiveMQConstant.ACTIVEMQ_USER_PW, ActiveMQConstant.ACTIVEMQ_URL);
actualConnectionFactory.setUseAsyncSend(useAsyncSendForJMS); 
//Active中的连接池工厂 
connectionFactory = new PooledConnectionFactory(actualConnectionFactory); 
connectionFactory.setCreateConnectionOnStartup(true); 
connectionFactory.setMaxConnections(maxConnections); 
connectionFactory.setMaximumActiveSessionPerConnection(maximumActiveSessionPerConnection);
logger.info("INIT ACTIVEMQ POOL CONNECTION FACTORY SUCCESS......");
} catch (Exception e) {
logger.error("ACTIVEMQ CONNECTION INIT ERROR......", e);
}
}
public void destroy(){
try {
if(connectionFactory != null){
connectionFactory.stop();
logger.info("STOP ACTIVEMQ CONNECTION FACTORY SUCCESS......");
}
} catch (Exception e) {
logger.error("STOP ACTIVEMQ CONNECTION FACTORY ERROR!!!", e);
}
}

/** 
* 从连接池获取链接
* @author 程松
* @date 2013-12-7 下午01:46:02 
* @return
* @see [类、类#方法、类#成员]
*/
public static Connection getConnection(){
try {
//从连接池工厂中获取一个连接 
Connection connection = connectionFactory.createConnection();
connection.start();
return connection;
} catch (JMSException e) {
e.printStackTrace();
}
return null;
}

/** 
* 链接打开session回话
* @author 程松
* @date 2013-12-7 下午01:46:19 
* @param conn
* @return
* @see [类、类#方法、类#成员]
*/
public static Session getSession(Connection conn){
Session session = null;
try {
//false 参数表示 为非事务型消息,后面的参数表示消息的确认类型 
session = conn.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE); 
} catch (JMSException e) {
e.printStackTrace();
}
return session;
}

/** 
* 创建一个生产者
* @author 程松
* @date 2013-12-7 下午01:48:14 
* @param session
* @return
* @see [类、类#方法、类#成员]
*/
public static MessageProducer getProducer(Session session, String queue_name){
try {
Destination destination = session.createQueue(queue_name);
MessageProducer producer = session.createProducer(destination); 
producer.setDeliveryMode(DeliveryMode.PERSISTENT);
return producer;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}

/** 
* 创建一个消费者
* @author 程松
* @date 2013-12-7 下午01:53:28 
* @param session
* @param queue_name
* @return
* @see [类、类#方法、类#成员]
*/
public static MessageConsumer getConsumer(Session session, String queue_name){
try {
Destination destination = session.createQueue(queue_name); 
MessageConsumer consumer = session.createConsumer(destination);
return consumer;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}

/** 
* 创建文本消息
* @author 程松
* @date 2013-12-7 下午02:05:05 
* @param session
* @param msg
* @return
* @throws JMSException
* @see [类、类#方法、类#成员]
*/
public static TextMessage getMessage(Session session, String msg) throws JMSException { 
TextMessage message = session.createTextMessage(msg); 
return message; 
}

/** 
* 创建对象消息
* @author 程松
* @date 2013-12-7 下午02:06:51 
* @param session
* @param obj
* @return
* @throws JMSException
* @see [类、类#方法、类#成员]
*/
public static ObjectMessage getMessage(Session session, Serializable obj) throws JMSException { 
ObjectMessage message = session.createObjectMessage(obj);
return message; 
}

/** 
* 创建map消息
* @author 程松
* @date 2013-12-7 下午02:17:58 
* @param session
* @param map
* @return
* @throws JMSException
* @see [类、类#方法、类#成员]
*/
public static MapMessage getMessage(Session session, Map map) throws JMSException { 
MapMessage message = session.createMapMessage();
Set<String> set = map.keySet();
Iterator<String> it = set.iterator();
while(it.hasNext()){
String key = it.next();
String value = String.valueOf(map.get(key));
message.setString(key, value);
}
return message; 
}

/** 
* 发送文本消息
* @author 程松
* @date 2013-12-7 下午02:30:46 
* @param model
* @see [类、类#方法、类#成员]
*/
public static void send(final String msg, final String queue_name) { 
//直接使用线程池来执行具体的调用 
threadPool.execute(new Runnable(){ 
public void run() { 
try { 
sendMsg(msg, queue_name); 
} catch (Exception e) { 
e.printStackTrace(); 
} 
} 
}); 
} 

/** 
* 真正的执行消息发送 
* @author 程松
* @date 2013-12-7 下午02:33:02 
* @param msg
* @param queue_name
* @throws Exception
* @see [类、类#方法、类#成员]
*/
private static void sendMsg(String msg, String queue_name) throws Exception { 

Connection connection = null; 
Session session = null; 
try { 
//从连接池工厂中获取一个连接 
connection = ActivemqConnectionFactory.getConnection(); 
session = ActivemqConnectionFactory.getSession(connection); 
MessageProducer producer = ActivemqConnectionFactory.getProducer(session, queue_name); 
Message message = ActivemqConnectionFactory.getMessage(session, msg); 
producer.send(message); 
} finally { 
ActivemqConnectionFactory.closeSession(session); 
ActivemqConnectionFactory.closeConnection(connection); 
} 
}

/** 
* 发送对象消息
* @author 程松
* @date 2013-12-7 下午02:33:40 
* @param model
* @param queue_name
* @see [类、类#方法、类#成员]
*/
public static void send(final QueueModel model, final String queue_name) { 
//直接使用线程池来执行具体的调用 
threadPool.execute(new Runnable(){ 
public void run() { 
try { 
sendMsg(model, queue_name); 
} catch (Exception e) { 
e.printStackTrace(); 
} 
} 
}); 
} 

/** 
* 真正的执行消息发送 
* @author 程松
* @date 2013-12-7 下午02:36:44 
* @param model
* @param queue_name
* @throws Exception
* @see [类、类#方法、类#成员]
*/
private static void sendMsg(QueueModel model, String queue_name) throws Exception { 

Connection connection = null; 
Session session = null; 
try { 
//从连接池工厂中获取一个连接 
connection = ActivemqConnectionFactory.getConnection(); 
session = ActivemqConnectionFactory.getSession(connection); 
MessageProducer producer = ActivemqConnectionFactory.getProducer(session, queue_name); 
Message message = ActivemqConnectionFactory.getMessage(session, model); 
producer.send(message); 
} finally { 
ActivemqConnectionFactory.closeSession(session); 
ActivemqConnectionFactory.closeConnection(connection); 
} 
}

/** 
* 发送MAP消息
* @author 程松
* @date 2013-12-7 下午02:34:29 
* @param model
* @see [类、类#方法、类#成员]
*/
public static void send(final Map map, final String queue_name) { 
//直接使用线程池来执行具体的调用 
threadPool.execute(new Runnable(){ 
public void run() { 
try { 
sendMsg(map, queue_name); 
} catch (Exception e) { 
e.printStackTrace(); 
} 
} 
}); 
} 

/** 
* 真正的执行消息发送 
* @author 程松
* @date 2013-12-7 下午02:36:14 
* @param map
* @param queue_name
* @throws Exception
* @see [类、类#方法、类#成员]
*/
private static void sendMsg(Map map, String queue_name) throws Exception { 

Connection connection = null; 
Session session = null; 
try { 
//从连接池工厂中获取一个连接 
connection = ActivemqConnectionFactory.getConnection(); 
session = ActivemqConnectionFactory.getSession(connection); 
MessageProducer producer = ActivemqConnectionFactory.getProducer(session, queue_name); 
Message message = ActivemqConnectionFactory.getMessage(session, map); 
producer.send(message); 
} finally { 
ActivemqConnectionFactory.closeSession(session); 
ActivemqConnectionFactory.closeConnection(connection); 
} 
}



/** 
* 获取文本消息
* @author 程松
* @date 2013-12-7 下午02:18:13 
* @param message
* @return
* @see [类、类#方法、类#成员]
*/
public static String getText(Message message){
if (message instanceof TextMessage) { 
//强制转换一下 
TextMessage txtMsg = (TextMessage) message; 
//输出接收到的消息 
String model = null;
try {
model = txtMsg.getText();
return model;
} catch (JMSException e) {
e.printStackTrace();
}
}
return null;
}

/** 
* 获取对象消息
* @author 程松
* @date 2013-12-7 下午02:18:41 
* @param message
* @return
* @see [类、类#方法、类#成员]
*/
public static Object getObject(Message message){
if (message instanceof ObjectMessage) { 
//强制转换一下 
ObjectMessage txtMsg = (ObjectMessage) message; 
//输出接收到的消息 
Object model = null;
try {
model = txtMsg.getObject();
return model;
} catch (JMSException e) {
e.printStackTrace();
}
}
return null;
}

/** 
* 获取map消息
* @author 程松
* @date 2013-12-7 下午02:19:00 
* @param message
* @return
* @see [类、类#方法、类#成员]
*/
public static Map getMap(Message message){
if (message instanceof MapMessage) { 
//强制转换一下 
MapMessage txtMsg = (MapMessage) message; 
//输出接收到的消息 
Map map = new HashMap();
try {
Enumeration<String> e = txtMsg.getMapNames();
while(e.hasMoreElements()){
String key = e.nextElement();
map.put(key, txtMsg.getString(key));
}
return map;
} catch (JMSException e) {
e.printStackTrace();
}
}
return null;
}

/** 
* 关闭回话
* @author 程松
* @date 2013-12-7 下午01:46:55 
* @param session
* @see [类、类#方法、类#成员]
*/
public static void closeSession(Session session) { 
try { 
if (session != null) { 
session.close(); 
} 
} catch (Exception e) { 
e.printStackTrace(); 
} 
} 

/** 
* 关闭链接
* @author 程松
* @date 2013-12-7 下午01:47:06 
* @param connection
* @see [类、类#方法、类#成员]
*/
public static void closeConnection(Connection connection) { 
try { 
if (connection != null) { 
connection.close(); 
} 
} catch (Exception e) { 
e.printStackTrace(); 
} 
}

}

spring.xml中配置:

<!-- actviemq factory -->
<bean class="com.lejob.lejobsearch.index.queue.ActivemqConnectionFactory" init-method="init" destroy-method="destroy">
</bean>

,项目启动时加载初始化ActivemqConnectionFactory。

项目中ActivemqConnectionFactory.send(param,queue_name);发送消息。

 

下面是消息消费者:IMessageHandler.java(消息处理任务接口)、RecrQueueMessageHandler.java(消息处理类)、RecrQueueConsumer.java(JMS消息消费者)、MultiThreadMessageListener.java(消息消费者中使用的多线程消息监听服务)、FixedAndBlockedThreadPoolExecutor.java(支持阻塞的固定大小的线程池)

IMessageHandler.java

package com.lejob.lejobsearch.index.queue;

import javax.jms.Message;

 

/**
* 提供消息操作的回调接口
* 
* @author 程松
* @date 2013-12-7上午10:49:49
* @company 乐享网络(5lejob)北京研发中心
* @version [Copyright (c) 2013 V001]
* @see [相关类/方法]
* @since [产品/模块版本]
*/
public interface IMessageHandler { 

/** 
* 消息回调提供的调用方法 
* @author 程松
* @date 2013-12-7 上午10:28:58 
* @param message
* @see [类、类#方法、类#成员]
*/
public void handle(Message message); 

}

 

RecrQueueConsumer.java

package com.lejob.lejobsearch.index.queue.recruitment;

import javax.jms.Connection;
import javax.jms.ExceptionListener;
import javax.jms.JMSException;
import javax.jms.MessageConsumer;
import javax.jms.Session;

import org.apache.log4j.Logger;

import com.lejob.lejobsearch.index.queue.ActiveMQConstant;
import com.lejob.lejobsearch.index.queue.ActivemqConnectionFactory;
import com.lejob.lejobsearch.index.queue.IMessageHandler;
import com.lejob.lejobsearch.index.queue.MultiThreadMessageListener;

 


/**
* JMS消息消费者 
* 
* @author 程松
* @date 2013-11-30下午04:00:09
* @company 乐享网络(5lejob)北京研发中心
* @version [Copyright (c) 2013 V001]
* @see [相关类/方法]
* @since [产品/模块版本]
*/
public class RecrQueueConsumer implements ExceptionListener { 

private Logger logger = Logger.getLogger(RecrQueueConsumer.class);

/**
* 监听消息线程最大值
*/
private static final int THREAD_COUNT = 1;
/**
* 消息处理类
*/
private IMessageHandler messageHandler;

private Connection connection;
private Session session;

public void init(){
try {
connection = ActivemqConnectionFactory.getConnection(); 
//会话采用非事务级别,消息到达机制使用自动通知机制 
session = ActivemqConnectionFactory.getSession(connection); 
MessageConsumer consumer = ActivemqConnectionFactory.getConsumer(session, ActiveMQConstant.RECR_QUEUE); 
consumer.setMessageListener(new MultiThreadMessageListener(THREAD_COUNT, messageHandler));
logger.info(ActiveMQConstant.RECR_QUEUE + " LISTENER INIT SUCCESS......");
} catch (Exception e) {
logger.error("处理队列" + ActiveMQConstant.RECR_QUEUE + "信息 异常", e);
}
}
public void destroy(){
try {
ActivemqConnectionFactory.closeSession(session);
ActivemqConnectionFactory.closeConnection(connection);
logger.info(ActiveMQConstant.RECR_QUEUE + " LISTENER DESTROY SUCCESS......");
} catch (Exception e) {
logger.error("关闭监听队列" + ActiveMQConstant.RECR_QUEUE + " 异常", e);
}
}

public void onException(JMSException e) { 
e.printStackTrace(); 
}

public void setMessageHandler(IMessageHandler messageHandler) {
this.messageHandler = messageHandler;
}



}

 

MultiThreadMessageListener.java

package com.lejob.lejobsearch.index.queue.recruitment;

import java.util.concurrent.ExecutorService;

import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.ObjectMessage;

import com.lejob.lejobsearch.index.queue.MessageHandler;
import com.lejob.rpc.search.model.QueueModel;

/** 
* 消息消费者中使用的多线程消息监听服务 
* 
*/ 
public class MultiThreadMessageListener implements MessageListener { 

//默认线程池数量 
public final static int DEFAULT_HANDLE_THREAD_POOL=10; 
//最大的处理线程数. 
private int maxHandleThreads; 
//提供消息回调调用接口 
private MessageHandler messageHandler; 

private ExecutorService handleThreadPool; 


public MultiThreadMessageListener(MessageHandler messageHandler){ 
this(DEFAULT_HANDLE_THREAD_POOL, messageHandler); 
} 

public MultiThreadMessageListener(int maxHandleThreads,MessageHandler messageHandler){ 
this.maxHandleThreads=maxHandleThreads; 
this.messageHandler=messageHandler; 
//支持阻塞的固定大小的线程池(自行手动创建的) 
this.handleThreadPool = new FixedAndBlockedThreadPoolExecutor(this.maxHandleThreads); 
} 


/** 
* 监听程序中自动调用的方法 
*/ 
public void onMessage(final Message message) { 
//使用支持阻塞的固定大小的线程池来执行操作 
this.handleThreadPool.execute(new Runnable() { 
public void run() { 
try {
if (message instanceof ObjectMessage) { 
//强制转换一下 
ObjectMessage txtMsg = (ObjectMessage) message; 
//输出接收到的消息 
QueueModel model = null;
try {
model = (QueueModel) txtMsg.getObject();
MultiThreadMessageListener.this.messageHandler.handle(model); 
} catch (JMSException e) {
e.printStackTrace();
}
}
} catch (Exception e) { 
e.printStackTrace(); 
} 
} 
}); 
} 

}

 

FixedAndBlockedThreadPoolExecutor.java

package com.lejob.lejobsearch.index.queue.recruitment;

import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

** 
* 支持阻塞的固定大小的线程池 
* 
*/ 
public class FixedAndBlockedThreadPoolExecutor extends ThreadPoolExecutor { 


//一个可重入的互斥锁 Lock,它具有与使用 synchronized 方法和语句所访问的隐式监视器锁相同的一些基本行为和语义,但功能更强大。 
//使用 lock 块来调用 try,在之前/之后的构造中 
private ReentrantLock lock = new ReentrantLock(); 

private Condition condition = this.lock.newCondition(); 

public FixedAndBlockedThreadPoolExecutor(int size) { 
super(size, size, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); 
} 


/** 
* 当线程池中没有空闲线程时,会挂起此方法的调用线程.直到线程池中有线程有空闲线程. 
*/ 
@Override 
public void execute(Runnable command) { 
//进行同步锁定 
this.lock.lock(); 
super.execute(command); 
try { 
//如果线程池的数量已经达到最大线程池的数量,则进行挂起操作 
if (getPoolSize() == getMaximumPoolSize()) { 
this.condition.await(); 
} 
} catch (InterruptedException e) { 
e.printStackTrace(); 
} finally { 
this.lock.unlock(); 
} 
} 

@Override 
protected void afterExecute(Runnable r, Throwable t) { 
super.afterExecute(r, t); 
try { 
this.lock.lock(); 
this.condition.signal(); 
} finally { 
this.lock.unlock(); 
} 
} 


}

 

项目spring.xml文件中配置

<!-- 任务处理类 -->

<bean id="recrQueueMessageHandler" class="com.lejob.lejobsearch.index.queue.recruitment.RecrQueueMessageHandler">
</bean>


<!-- JMS消息消费者 -->

<bean class="com.lejob.lejobsearch.index.queue.recruitment.RecrQueueConsumer" init-method="init" destroy-method="destroy">
<property name="messageHandler" ref="recrQueueMessageHandler"></property>
</bean>

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值