2012-04-20 15 views
1

我使用jboss5.1,EJB3.0和獨立的Java應用解決方案的Thread.sleep爲「用戶」裏面EJB

我有機制,通過JMS主題發佈消息給用戶。 當用戶收到消息時,它需要做很少的操作,直到它將開始再次收聽未來的消息。

的問題是,如果一個用戶獲得從主題相關的消息就需要回到足夠快監聽進一步消息(否則會錯過它在另一條消息將公佈的情況下)

所以我的解決方案是在ejb發佈者內部放置幾秒的Thread.sleep()。

這種方式確保所有訂閱者在發佈新消息之前都會回聽。

我知道不推薦使用EJB內部的Thread。

該場景的任何解決方案?

謝謝, 射線。

+1

你是什麼意思「它會錯過它?」看起來你有一個設計問題,當你說:「它將需要足夠快地恢復......」幾乎不會依賴於某些代碼的執行速度會足夠快的事實。它應該工作,它需要1ms或1小時 – 2012-04-20 07:55:14

+0

我想你是對的。你將如何重新設計它,使訂戶能夠始終接收消息? – rayman 2012-04-20 09:13:05

+1

對不起,我不是JMS專家,所以我不知道它是如何工作的以及你可以做出什麼假設。我不明白你爲什麼會錯過任何信息。如果您忙於做其他事情,則該消息應排隊,但不能丟棄。您的意思是您的用戶在處理收到的消息時會停止收聽新消息,並在他們完成後再次開始收聽? – 2012-04-20 09:30:17

回答

1

好了,你的問題其實是,你停止在處理消息時收聽JMS隊列,然後註冊自己。當然,在處理前一個消息時,你可能會錯過消息。

我建議不要從JMS隊列註銷自己,爲了確保您一次處理一條消息,可以使用單個線程池來處理您的請求。

例如,如果之前你有這樣的事情:

public void onNewJMSMessage(JMSMessage message) { 
    unregisterMySelf(); 
    processMessage(message); 
    registerMySelf(); 
} 

用這個代替:

啓動類成員是這樣的:

private ExecutorsService processingPool = Executors.newSingleThreadExecutor(); 

public void onNewJMSMessage(final JMSMessage message) { 
    processingPool.submit(new Runnable() { 

     @Override 
     public void run() { 
       processMessage(message); 
     } 
    }); 
} 

Thi s將保證一次只處理一條消息(如果封閉類是唯一的,否則你將不得不設置一個單例來確保單線程池的唯一性)。

這樣做後,這將主要允許您刪除您的EJB中的Thread.sleep,這是邪惡的和各種令人頭痛的問題。

+0

這可能會導致大量增長的內存消耗。如果發生OutOfMemoryerror,所有消息都可能丟失。我會建議一個持續的queu /主題。 (-1) – 2012-04-20 14:12:50

+0

@ckuetbach我沒有足夠的上下文來了解消息的重要性,也不知道消息有多大,消息有多少。它說,他有一個獨立的應用程序,所以對於JEE應用程序以外的我,您可能擁有無狀態軟件,這些軟件只是客戶端在關閉時(無論是否願意)可能丟失或丟失一些消息。如果他之前有某種方法來正確存儲消息,他當然可以恢復。 – 2012-04-20 14:20:49

+0

是的,你說得對,問題不是很確切。 – 2012-04-20 14:22:23

2

恕我直言,你不應該把發佈者的線程置於睡眠狀態。根據定義,當使用JMS和消息驅動bean時,您可以保證郵件將被傳遞。唯一不能保證的是訂單:消息驅動Bean可能會以與它們發送的訂單不同的順序獲取消息。

而且,隨着JMS工作的全部意義在於讓你異步發送消息(即使你實際上可以配置你的隊列/主題同步工作)

0

我知道這個線程很舊,但我覺得不得不加我兩分錢。我同意Kyiu上面所說的。

根據EJB2規範,企業bean不應該管理線程。我不確定最新規格對此有什麼要說的,但如果這一點發生了變化,我會感到震驚。

問題在於JMS被設計成使消息不會丟失。所以,不管怎樣,MDB都會消費這些消息。另外,應該記住,MDB(與其他EJB一樣)是容器管理的。你爲什麼認爲只有一個MDB實例會消耗你的消息(當然,除非你把它設計成這種方式,我相信不是這種情況)。