2015-06-18 46 views
2

我们的应用程序运行在WebLogic 12c中,它正在从排队系统中检索消息,其中我们检索消息的队列被配置为FIFO。我们使用Spring来配置检索功能,并且容器(org.springframework.jms.listener.DefaultMessageListenerContainer)和消息监听器(org.springframework.jms.core.support.JmsGatewaySupport)都是单例。此外,该容器默认将工作管理器配置为任务执行程序。为了保证消息按照预期的顺序处理(它们被发送到队列的顺序),我们在监听器中使用ReentrantLock,并且我们期望消息被逐个检索和处理。听者代码是下列之一:线程获取已被其他线程获取的ReentrantLock

public class JmsReceiveAdapterImpl extends JmsGatewaySupport implements SessionAwareMessageListener { 
    private final ReentrantLock lock = new ReentrantLock(true); 
    [...] 
    public void onMessage(Message rcvMessage, Session session) throws JMSException { 
     lock.lock(); 
     logger.warn("Lock has been acquired by thread: " + Thread.currentThread().getId()); 
     try { 
      [...] 
     } finally { 
      logger.warn("Lock is going to be released by thread: " + Thread.currentThread().getId()); 
      lock.unlock(); 
     } 
    } 
}

即使两个消息被放置在队列中以正确的顺序,它们被消耗的顺序(召回该队列是一个FIFO之一),以某种方式在两个消息由应用程序并行处理,如以下日志块所示:

 
    Lock has been acquired by thread: 28 
    Backout count: 1 
    Message 1/1 received from XXX Message ID1 received. 
    Lock has been acquired by thread: 54 
    Backout count: 1 
    Message 1/1 received from XXX Message ID2 received. 
    ***** ERROR ***** 
    Lock is going to be released by thread: 54 
    Lock is going to be released by thread: 28 

为什么我们要获得此行为?任何想法?

非常感谢你的进步。

+7

考虑到'ReentrantLock'不工作的机会接近零,我建议你输出'this'到日志,以确保你的班级是一个单身人士。 – user3707125

+1

同时检查你是否在这个锁创建的某些条件下不调用'await()'。 – talex

+0

如果你想绝对确定,你可以将锁定为静态,但是从设计的角度来看,这将是一场灾难 –

回答

3

变化

logger.warn("Lock has been acquired by thread: " + Thread.currentThread().getId()); 

logger.warn("Lock has been acquired by thread: " + Thread.currentThread().getId() + " And Object " + System.identityHashCode(this)); 

你将可能看到什么就是System.identityHashCode将是两个不同的号码。如果它是相同的对象,则identityHashCode将是相同的。如果它们不同,那就意味着它们是不同的对象。

告诉你的是,有多个ReentrantLock实例,并且不会支持差异实例上的互斥。

+0

非常感谢,约翰。我要执行你的建议。只要我获得结果,我会在这里分享。 –