2015-06-18 85 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

非常感謝,約翰。我要執行你的建議。只要我獲得結果,我會在這裏分享。 –