2009-08-11 13 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); 
    } 
} 

が、私は(M)message_queue.putを呼び出します。たとえば、私はこのような何かを持っています。問題ない!私の質問は次のとおりです:

一度に一組のメッセージを一斉に追加するにはどうすればよいですか?のは、私はこれをしたいとしましょう:

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

問題は、別のスレッドが同じことをやっている可能性があることですし、一つのスレッドからのメッセージは、私が意図したとおりにキューに登録されることが保証されていません。競合するスレッドからのメッセージは、間に「インターリーブ」されることがあります(つまり、実際のシーケンスは、A、A、A、B、B、Bの代わりにA、A、B、B、A、Bになります) "put"の例のループを "synchronized(message_queue){}"ブロックに入れることができますが、同じブロックを.take()の呼び出しの周りに置く必要がありますか?そして、明らかに、デッドロック状況を即座に作り出すので、私はそれを行うことはできません。新しいMessageがput()されるまでブロックします。これは同期によってロックされても起こりません。 take()コールでsynchronizedブロックをスキップし、putループの同期ブロックのみを持ち、目的の効果を得ることはできますか?ありがとう!

答えて

2

残念ながら、LinkedBlockingQueue内の個々のputとtakeロックにはアクセスできません。プライベートであるためです。

あなたが言及しているように、このアトミック化を行うブロック​​に一括処理をラップするだけでよいでしょう。これを行うと、take()操作の周りに​​ブロックを追加する必要があると述べた理由がわかりません。私はこの2番目の同期ブロックが必要であるとは思わない(とにかくLinkedBlockingQueueはスレッドセーフです)。

+0

は、合意された:のみ発注の問題がかどうかであります2つのバルクプット操作が互いに衝突するか、または1つのプット操作で衝突します。 –

2

キューに入れたい(離陸する)オブジェクトはおそらくグループののメッセージでしょうか?

おそらく、メッセージの順序付きコレクションを表すオブジェクトがあります。通常、メッセージには1つのメッセージしか含まれていませんが、このシナリオでは多くのメッセージが含まれています。それは原子性と順序を維持するでしょう。

+0

1 BAH ...私はまだそれに – basszero

+0

良いアイデアを、私を打つ:(私の応答を入力しましたが、それはあなたが一度に1つのメッセージをやってのけるしたい場合は、物事を複雑にし –

関連する問題