2009-08-11 63 views
1

我使用LinkedBlockingQueue處理來自其他線程的消息對象。例如,我有這樣的事情:Java:使用對象列表同步put()

LinkedBlockingQueue<Message> message_queue = new LinkedBlockingQueue<Message>(); 

public void run(){ 
    while(true){ 
     Message m = message_queue.take(); 
     handle_message(m); 
    } 
} 

當我從另一個線程添加一個新的消息,我打電話message_queue.put(M)。沒問題!我的問題是這樣的:

如何同時添加一組消息?比方說,我想這樣做:

Message[] messages = {/* some list of message objects */}; 
for (Message m : messages){ 
    message_queue.put(m); 
} 

的問題是,另一個線程可以做同樣的事情,並從一個線程的消息不能保證,因爲我打算準確地排隊。來自競爭線程的消息可以在它們之間「交錯」(即,實際的序列可以最終成爲A,A,B,B,A,B而不是預期的A,A,A,B,B,B)可以將循環放在「put」示例中的「synchronized(message_queue){}」塊中,但是我是否也需要將相同的塊放到.take()的調用中?顯然,我不能這樣做,因爲它會立即創建一個死鎖情況,因爲take()阻塞,直到放入一個新的消息(),這在鎖定同步時不會發生。我可以跳過take()調用中的同步塊,在put循環中只有一個同步塊,並獲得所需的效果嗎?謝謝!

回答

2

不幸的是,您不能訪問個人存款並在LinkedBlockingQueue之內取鎖,因爲它們是私密的。

正如你所說的,你可以簡單地將批量放置操作包裝在​​塊中,這會使其成爲原子。如果你這樣做,我不明白你爲什麼說你還需要添加一個​​塊圍繞take()操作。我不相信需要第二個同步塊(因爲LinkedBlockingQueue無論如何都是線程安全的)。

+0

同意:唯一的順序問題是2次大宗投機操作相互衝突或單次投放操作。 – 2009-08-11 16:39:24

2

也許您想放入隊列(並起飛)的對象是組的消息?

即也許你有一個對象表示一個有序的消息集合。通常它只包含一條消息,但可以(在這種情況下)包含很多消息。這將保持原子性和順序。

+0

+1 bah ...我還在打我的回覆:(打我吧:) – basszero 2009-08-11 16:26:33

+0

好主意,但它確實複雜的事情,如果你想一次拉出1條消息。 – 2009-08-11 16:40:35