开发过程中遇到一个activemq死锁的问题,痛苦经历:
应用场景:
- 后台进程(appserver1)不断产生任务, 发送到queue上
- 前台应用(appservers)请求过来,到queue上获取消息,并根据消息取对应数据
问题:
多线程到同一个queue上直接调用receive,收消息时,会将queue锁住:
服务器端dump出来的信息如下:
ound one Java-level deadlock: ============================= "tcp:///10.0.72.76:52012": waiting to lock monitor 0x080ead4c (object 0x952b6950, a java.util.LinkedList), which is held by "tcp:///10.0.72.76:52010" "tcp:///10.0.72.76:52010": waiting to lock monitor 0x080ead8c (object 0x8e7f6620, a org.apache.activemq.broker.region.QueueSubscription), which is held by "tcp:///10.0.72.76:52012" |
在activemq论坛上发现如下内容patch:
在4.1以及之前的版本,需要自己按以下方式修改源代码
Index: activemq-core/src/main/java/org/apache/activemq/ActiveMQSessionExecutor.java =================================================================== --- activemq-core/src/main/java/org/apache/activemq/ActiveMQSessionExecutor.java (revision 480716) +++ activemq-core/src/main/java/org/apache/activemq/ActiveMQSessionExecutor.java (revision 480717) @@ -63,8 +63,11 @@ public void wakeup() { if( !dispatchedBySessionPool ) { - if( taskRunner!=null ) { + if( session.isSessionAsyncDispatch() ) { try { + if( taskRunner == null ) { + taskRunner =session.connection.getSessionTaskRunner().createTaskRunner(this,"ActiveMQ Session: "+session.getSessionId()); + } taskRunner.wakeup(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); @@ -101,10 +104,8 @@ synchronized void start() { if( !messageQueue.isRunning() ) { messageQueue.start(); - if( session.isSessionAsyncDispatch() || dispatchedBySessionPool ) { - taskRunner =session.connection.getSessionTaskRunner().createTaskRunner(this,"ActiveMQ Session: "+session.getSessionId()); - } - wakeup(); + if( hasUncomsumedMessages() ) + wakeup(); } } |
该问题在4.1.1和4.2中已经解决,不过目前这两个版本都还没有release。用activemq的同学要小心了。