32

ArrayListsデータのキューとして機能するものがいくつかあります。各キューは個々のスレッドにリンクされており、スレッドにデータが含まれているかどうかがチェックArrayListされます。

 while (array.size == 0) {
    // nothing
 }

 // do stuff with one element of the array
 // remove element from array
 // and call the loop again

組み込みシステムプログラミングでも同様のことをしましたが、Javaで使用しても安全ですか?懸念されるのは、whileループを非常に高速に繰り返すことによるプロセス電力の浪費です。

Thread.sleep(100)100ミリ秒ごとに追加してチェックすることで解決できますが、応答時間が遅くなります。

問題は、その睡眠を追加する必要があるのか​​、それとも心配する必要がないのかということです。

アレイ内の新しいデータをチェックするためのより安全でより良いシステムに関する提案はありますか?

4

7 に答える 7

52

ArrayListはスレッドセーフなコレクションではないため、あるスレッドがリストにデータを追加し、別のスレッドが同じリストからデータを取得しようとした場合、他のスレッドが追加された要素を認識できる保証はありません。

そして、あなたが説明するような忙しい待機は、CPUリソースを不必要に消費します。

キューが必要なようですので、のようにキューを使ってみませんかArrayBlockingQueue。アイテムがキューに追加されるまで、CPUサイクルを消費せずにブロックするtakeメソッドがあります。そして、それはスレッドセーフです。

于 2012-08-28T12:52:21.720 に答える
11

待機する必要のある時間が非常に短く、コンテキストスイッチが高すぎる場合を除いて、回転は使用しません。正当な理由もなく、CPUサイクルを確実に浪費します。

wait/notifyまたはその他のシグナリングメカニズムを使用して、スレッドを一時停止し、必要な場合にのみウェイクアップする必要があります。

より高度な構造に行くと、BlockingQueue(実装を選択)のような生産者/消費者パターンに特化したデータ構造があります。

要素を取得するときにキューが空でなくなるのを待ち、要素を格納するときにキューでスペースが使用可能になるのを待つ操作を追加でサポートするキュー。

于 2012-08-28T12:51:10.233 に答える
1

java.lang.ArrayListスレッドセーフではありません。キューイングの目的で、を使用することをお勧めしますBlockingQueue。CPUを消費せずにキューが空の場合、スレッド呼び出しをブロックします。ArrayBlockingQueue必要に応じて、またはLinkedBlockingQueueその他のキュー実装を使用できます。

で実装することもできますがwait and notifyAll、常に使用することをお勧めしますBlockingQueue

于 2012-08-28T13:10:06.077 に答える
1

java 5でリリースされたブロッキングキューのようなものを使用するのはどうですか。これは、非常に複雑になる可能性がある待機/通知よりも今推奨されていると思います。私はそれを使用しました、そしてそれはうまくいきます。

http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/BlockingQueue.html

于 2012-08-28T12:52:52.737 に答える
1

ArrayListを使用する代わりに、Concurrentコレクションを使用できます。たとえば、ArrayBlockingQueueなどです。

ArrayBlockingQueue<YourObject> theQueue;
while(true) {
  YourObject o = theQueue.take();
 //process your object
}

あなたがあなたの列を埋める他の場所では、あなたはただ

theQueue.add(theElement);

オブジェクトを待機しているスレッドは、要素が存在するまで「スリープ」します。addメソッドは、消費スレッドをウェイクアップします。

このクラスの詳細については、http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/ArrayBlockingQueue.htmlを参照してください。

于 2012-08-28T13:14:33.320 に答える
0

スリープがないと、スレッドは可能な限り高速にループし、ArrayListにアクセスします。おそらく、ほとんどの場合、結果はありません。

リスナー/オブザーバーパターンを実装することをお勧めします。可能であれば、ArrayListを埋めるプロデューサーに、変更について適切なスレッドに通知してもらいます。したがって、ポーリング動作からプッシュ動作に移行します。

それがアーキテクチャ内で実行可能かどうかはわかりませんが、システムについてさらに説明する必要があります。

于 2012-08-28T12:53:16.760 に答える
0

ポーリングとは何ですか?それに関する問題は何ですか?

条件が真になるまで繰り返しテストするプロセスは、ポーリングと呼ばれます。

ポーリングは通常、特定の条件が真であるかどうかをチェックするためのループの助けを借りて実装されます。それが真の場合、特定のアクションが実行されます。これは多くのCPUサイクルを浪費し、実装を非効率的にします。たとえば、一方のスレッドがデータを生成し、もう一方のスレッドがデータを消費するという古典的なキューイングの問題では。

Javaマルチスレッドはこの問題にどのように対処しますか?

ポーリングを回避するために、Javaは3つのメソッド、つまり、、wait()およびnotify()を使用しnotifyAll()ます。

これらのメソッドはObjectすべてfinalとしてクラスに属しているため、すべてのクラスにメソッドがあります。これらは、同期されたブロック内でのみ使用する必要があります。

wait() -呼び出し元のスレッドに、ロックを解除して、他のスレッドが同じモニターに入り、を呼び出すまでスリープ状態にするように指示しますnotify()

notify()wait() -同じオブジェクトを呼び出した単一のスレッドを起動します。notify()呼び出しは実際にはリソースのロックを放棄しないことに注意してください。

notifyAll()wait() -同じオブジェクトを呼び出したすべてのスレッドをウェイクアップします。

ArrayListスレッドセーフなコレクションではありません。を使用しArrayBlockingQueueます。

クラスArrayBlockingQueue

于 2016-10-10T06:31:58.100 に答える