Javaで回転せずにブロックしますか?

java multithreading

Javaの特定のメソッドは、ServerSocket.accept()やInputStream.read()のように、何かができるまでブロックされますが、それをどのようにして行うのかを見つけるのは簡単ではありません。 私が考えることができる最も近いことは毎回Thread.sleep()でwhile()ループですが、睡眠期間が長くなればなるほど、ブロッキングの反応が悪くなり、睡眠が短くなればなるほど回転が速くなります。

2つ質問があります。

  1. 上記のようなさまざまな標準機能はどのようにブロックされますか。 ネイティブコード? while()ループ? 他に何か?

  2. ブロックするメソッドをどのように実装すればいいですか?

  4  5


ベストアンサー

あなたがリストした操作は、基盤となるプラットフォームのためにブロックされます(つまり、 ネイティブコード)

Javaの `Object.wait()`と `Object.notify()`メソッドを使ってブロックを実装することができます。 `wait()`は他のスレッドが同じロックで `notify()`を呼び出すまで呼び出し側のスレッドをブロックします。

10


(1)の本質的な答えは「心配しないで – OSがそれを処理する」です。 入力ストリームからの読み込みのようなものへの呼び出しは、基本的にはオペレーティングシステム呼び出しのラッパーです。 OS内部の内部では、このような場合に呼び出しが「ブロック」するときに通常起きていると思うのは、OSがディスクコントローラからのハードウェア割り込みを待っていることを「知っている」ということです。そのような要求されたデータは現在利用可能であり、そしてそれはスレッドXがそのデータを要求したものであることを知っている。 そのため、その割り込み(または「エラーが発生した」などの割り込み)を受け取るまで、スレッドXでは再度スケジュールされません。 (そして、スレッドスケジューリングアルゴリズムの一部は、待機しているスレッドに、その待たされたデータが利用可能になったときに一時的な「ブースト」を与えるなどのことを行っています。 繰り返しますが、通常はこれをあまり気にする必要はありません。別の言い方をすれば、このメカニズムの詳細が何であれ、一般的なJavaプログラマーには利用できません。

(2)では、「Thing Xをどうやってやればいいのか」ということについてもっと考えてみることをお勧めします。 Thing Xが意図的に単に「ブロック」するだけで、Thing Xがどのようなものであっても、それを実行するライブラリメソッド/クラスがあるのではないかと思うのです。 例えば(リンクは私がこれらの主題について書いたいくつかの資料を含みます):

  • 次のメッセージ/ジョブをキュー/プロバイダから利用可能になったときに受け取る場合は、http://www.javamex.com/tutorials/synchronization_producer_consumer_2.shtml [ブロックキュー]を参照してください。

  • 必要に応じてロックが使用可能になるのを待って、オブジェクトを「ロック」して共有リソースへのアクセスを制御する必要がある場合は、プレーン同期、またはhttp://www.javamex.com/tutorials/synchronization_concurrency_9_locksを検討してください。 shtml [明示的ロック];

  • たくさんの_プールされたリソース_が利用可能になるのを待ちたい場合は、http://www.javamex.com/tutorials/synchronization_concurrency_semaphore.shtml[semaphores]を参照してください。

私は、生のwait / notifyメカニズムは、Java 5の同時実行性APIではほとんど推奨されていないと思います。 そして、あなたがしていることが何であれ、スピンロックは通常一番最後の手段です。

6


(2)に答えるには、Objectメソッドをwait、notify、およびnotifyAllにします。

Object.wait()を使用するときは、待機している条件をチェックするループで待機を囲む必要があります。 wait()メソッドは誤って返すことがあります(微妙な理由で)。

また、notify()とnotifyAll()のどちらを使用する必要があるのか​​を考慮する必要があります。待機中のすべてのスレッドがまったく同じ状態を待機していて、通知されているものを処理するのに必要なスレッドだけが必要です。 notify()を使用できます。それ以外の場合はnotifyAll()を使用する必要があります。これは、どのスレッドがnotify()で通知されるかを保証するものではないためです。

最後に、java.util.concurrentパッケージをよく見てください。これには、Javaプリミティブを使用するよりも、スレッドに関する一般的な問題に対する、より高度な解決策が多数あります。

4


私はパート1に答えることができます。 各OSにはマルチタスクを有効にすることの一部としてシグナリングとブロッキングが既に組み込まれているので、それらはそれを処理するためにOSを使用します。

通常、独自の回転ロックコードを実装する必要がある場合は、どちらか間違った方法を使用しています。 回転しても、コードが何もしないためにまだ起きていなければならないスリープ状態でも、あらゆる形態の電力管理が削減されます。

2


タイトルとURLをコピーしました