BlockingQueue:put()とisEmpty()は連動しませんか?
-
19-08-2019 - |
質問
SynchronousQueue
を持つ1つのスレッドから要素を挿入するput()
が欲しいので、要素が別のスレッドに取り込まれるまで入力がブロックされます。
他のスレッドでは多くの計算を実行しますが、時々、要素が既に使用可能かどうかを確認し、それを消費したいと考えています。しかし、別のスレッドがisEmpty()
呼び出しで待機している場合でも、<=>は常にtrueを返すようです。
これはどのように可能ですか?サンプルコードは次のとおりです。
@Test
public void testQueue() throws InterruptedException {
final BlockingQueue<Integer> queue = new SynchronousQueue<Integer>();
Thread t = new Thread(new Runnable() {
@Override
public void run() {
while (true) {
if (!queue.isEmpty()) {
try {
queue.take();
System.out.println("taken!");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// do useful computations here (busy wait)
}
}
});
t.start();
queue.put(1234);
// this point is never reached!
System.out.println("hello");
}
編集: isEmpty()もpeek()も動作せず、poll()を使用する必要があります。ありがとう!
解決
からhttp://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/SynchronousQueue.html#put(E):
isEmpty
public boolean isEmpty()
常にtrueを返します。 SynchronousQueueには内部容量がありません。
(これについては詳細に検討していませんが、代わりに poll または take をご覧ください)
他のヒント
Timの答えに加えて、コンシューマスレッドでは何もしていませんが、タイトループでisEmpty()を継続的に呼び出しています。実行するのに役立つ何かがあるまでOSを実行しないように要求するのではなく、コンシューマスレッドは常にビジー状態です。 isEmptyが正しく機能していても、プロデューサースレッドが実行される機会はほとんどありません。
(isEmpty()が機能した場合、またはpoll()の使用に切り替えた場合)プロデューサーに実行の機会を与えるためにキューが空の場合、テスト間で消費者を少しスリープさせるか、または(できれば) isEmpty()テストを実行し、ポーリングの代わりに賢明な方法でtake()内のmutexでスレッドをブロックします。
あなたのコードは、あなたが投票しようとしているように見えます。 poll()メソッドを呼び出すだけではどうですか?