【开源中国 APP 全新上线】“动弹” 回归、集成大模型对话、畅读技术报告”
最近的程序一直在和websphere mq打交道,但是遇到很多问题,网上查资料几乎查不到什么结果。。。主要有一下几个问题,求大神来解答
1、事务
我看有一些例子,比如《IBM WebSphere MQ基础教程》这本书中,无论是往mq放消息还是取消息都调用了qMgr.commit(),而网上一些例子都没有调用该方法。所以什么时候该用,什么时候不用?
2、多线程访问mq
未充分利用CPU提升效率,应用是多线程的。多个线程同时访问一个队列从里面取消息会有问题吗?还是《IBM WebSphere MQ基础教程》这本书里有这么一段话:
但是,从网上某篇博客中又看到这么一句话:
我对访问mq的操作作了一个封装类MQGet,使用了单例。。。。应用是一个web应用,在servlet的init方法中先调用MQGet.getInstance().conn(),这样应用启动时就建立了连接;然后在开启的N多个线程中都调用MQGet.getInstance().getMsg()来取队列消息;在servlet的destroy方法中调用MQGet.getInstance().close()来关闭连接。
不知道这样做是否有问题,坐等大神指教。。
附MQGet类源码:
package com.tk.csc.service; import org.apache.log4j.Logger; import com.ibm.mq.MQEnvironment; import com.ibm.mq.MQException; import com.ibm.mq.MQGetMessageOptions; import com.ibm.mq.MQMessage; import com.ibm.mq.MQQueue; import com.ibm.mq.MQQueueManager; public class MQGet { private static final Logger logger = Logger.getLogger(MQGet.class); private static final String HOST = OverallProperties.getInstance().getPropertyStr("mqUrl"); private static final int PORT = OverallProperties.getInstance().getPropertyInt("mqPort"); private static final String CHANNEL = OverallProperties.getInstance().getPropertyStr("mqChannel"); private static final String QMANAGER = OverallProperties.getInstance().getPropertyStr("mqManager"); private static final String QNAME = OverallProperties.getInstance().getPropertyStr("mqName"); private static final int CCSID = 1208; private static final MQGet m = new MQGet(); private MQQueueManager qMgr; private MQQueue queue ; public static MQGet getInstance() { return m; } private MQGet() {} public boolean conn() { logger.info("trying to connect MQ:" + HOST+ ":" + PORT); MQEnvironment.hostname = HOST; MQEnvironment.channel = CHANNEL; MQEnvironment.CCSID = CCSID; MQEnvironment.port = PORT; MQEnvironment.properties.put("transport", "MQSeries"); try { qMgr = new MQQueueManager(QMANAGER, 0); } catch (MQException e) { logger.info("create mqmanager fail!" + e.getMessage()); return false; } try { queue = qMgr.accessQueue(QNAME, 8226, null, null, null); } catch (MQException e) { logger.info("accessQueue fail!" + e.getMessage()); return false; } return true; } public String[] getMsg() { int depth = 0; try { depth = queue.getCurrentDepth(); } catch (MQException e1) { logger.info("get queue depth fail!" + e1.getMessage()); } logger.info("当前队列深度==" + depth); if (depth <= 0) { return null; } MQGetMessageOptions gmo = new MQGetMessageOptions(); gmo.options = gmo.options + 2; gmo.options = gmo.options + 8192; MQMessage rcvMsg = new MQMessage(); try { queue.get(rcvMsg, gmo); } catch (MQException e) { logger.info("get msg from queue fail!" + e.getMessage()); } String[] s = null; try { s = (String[]) rcvMsg.readObject(); } catch (Exception e) { logger.info("execute readObject() fail!" + e.getMessage()); } return s; } public void close() { if (queue != null) { try { queue.close(); logger.info("close queue Success!"); } catch (MQException e) { logger.info("colse queue fail!"); }finally { if (qMgr != null) { try { qMgr.close(); qMgr.disconnect(); logger.info("close qMgr Success!"); } catch (MQException e) { logger.info("close qMgr fail !"); } } } } } }
在测试过程中偶尔出现队列深度queue.getCurrentDepth()一次减少2的情况,但是只有一个应用一个线程在取消息,每取走一条消息深度应该减1啊,,,