多线程工作环境下MQ get操作的阻塞问题

本文档探讨了在Java多线程环境中使用MQ时遇到的get操作阻塞问题。当使用MQGetMessageOptions.options设置为非MQC.MQGMO_NO_WAIT时,线程可能会阻塞。通过共享MQQueueManager实例(Spring中定义为singleton),导致线程间竞争,进而影响队列打开计数和消息获取。解决方法是将MQQueueManager的Scope改为prototype,确保每个线程拥有独立的实例,从而避免阻塞。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

使用Java语言编写MQ应用程序,少不免要使用多线程来提高并发性能。但在get操作时如果选择没有消息就等待的话(即MQGetMessageOptions.options使用MQC.MQGMO_NO_WAIT之外的选项时),就要考虑线程阻塞的问题了。

原来的思想是这样的,在Queue Manager里有两条队列,不妨设为Q01与Q02,我们需要用多条线程去打开这两个队列取出消息。为了避免线程问题,多个线程共享同一个MQQueueManager实例(用Spring中的Scope=singleton指定),而在每个线程中使用accessQueue打开队列,再用一个while(true)不断取出队列中的消息。暂定各用2条线程分别取出Q01与Q02的消息。

但这时问题出现了,运行程序后,在MQ Explorer中查看队列的打开输入计数(即get操作打开队列的个数),原本Q01与Q02应各为两个,但实际上有时只有1个,有时没有,达到预期结果的次数很少。而且有时候明明队列里有消息,队列也已经打开了,但程序就是没有把消息取出来。

调试了比较久也没发现问题出在哪里,后来查看WebSphere MQ Using Java (csqzaw15)这份文档时,发现了以下的提示:

If  you  perform  a  get  with  wait,  all  other  threads  using  the  same MQQueueManager  are  blocked  until  the  call  completes.  If  you  need  multiple threads  to  access  WebSphere  MQ  simultaneously,  then  each  thread  must  create  its own  MQQueueManager  object.

意思是如果在get的时候使用等待选项,使用同一个MQQueueManager 实例的其他线程在get操作完成之前都会被阻塞。要用多条线程同时访问 WebSphere  MQ,就要为每条线程制定各自的MQQueueManager 对象实例。

--WebSphere MQ Using Java (csqzaw15) Page168

这才找到了问题所在,原来我在Spring中指定了全部线程都使用同一个MQQueueManager实例,所以在某条线程get其中一个队列的消息时,如果队列中没有消息则它会阻塞,从而导致了其他3条线程都堵塞了。这时如果其他线程还没有执行accessQueue操作打开队列的话,MQ Explorer中就当然不会看到输入计数增加。若另一队列里有消息,也会因为线程被阻塞导致不能把消息取出。

在Spring配置文件中将MQQueueManager的Scope改成prototype,问题就解决了……

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值