ホームページ  >  記事  >  Java  >  Javaマルチスレッドにおけるスレッド間通信の詳細説明

Javaマルチスレッドにおけるスレッド間通信の詳細説明

黄舟
黄舟オリジナル
2017-09-14 10:51:422393ブラウズ

次のエディターは、Java マルチスレッド プログラミングの学習 (スレッド間通信) に関する記事をお届けします。編集者はこれがとても良いと思ったので、参考として共有します。エディターをフォローして、一緒に見てみましょう

1. 概要

オペレーティングシステムではスレッドは独立した個体ですが、これらの個体は特別な処理をしないと全体になりません。スレッド間の通信は全体として一つになります。必須のソリューションを紹介します。スレッドが通信できるようになると、システム間の対話性がより強力になり、CPU 使用率が大幅に向上すると同時に、プログラマーが各スレッドのタスクの処理を効果的に制御および監視できるようになります。

2. 待機/通知メカニズム

1. "待機/通知" メカニズム: 待機/通知メカニズム。待機によりスレッドが一時停止され、通知により一時停止されたスレッドが実行を継続します。シェフとウェイターのやり取りを使って説明してみましょう:

(1) ウェイターが料理を受け取る時間はシェフに依存するため、ウェイターは「待ち」状態になります。

(2) シェフが料理を「配膳テーブル」に置くと、初めてウェイターが料理を受け取り、食事者に渡すことができます。

2. wait()

(1) は、現在コードを実行しているスレッドを待機させます。 wait() メソッドは、Object クラスのメソッドです。このメソッドは、現在のスレッドを「実行前キュー」に配置し、通知が受信されるまで、wait() が配置されているコード行で実行を停止するために使用されます。中断されました。

(2) wait() メソッドを呼び出す前に、スレッドはオブジェクトのオブジェクトレベルのロックを取得する必要があります。つまり、wait() メソッドは同期メソッドまたは同期ブロックでのみ呼び出すことができます。それ以外の場合は、IllegalMonitorStateException 例外が発生します。投げられるだろう。 (Runtime のサブクラスに属し、例外をキャッチするために try-catch ステートメントは必要ありません)

(3) wait() メソッドを呼び出した後、現在のスレッドはロックを解放し、このオブジェクトはスレッド待機プールに入ります。目覚めるのを待っています。 wait() から戻る前に、スレッドはロックを取り戻すために他の待機スレッドと競合します。

(4) wait() メソッドは割り込みにより中断され、InterruptedException をスローすることができます。

(5) wait(long): 1 つのパラメーターを持つ wait(long) メソッドの機能は、スレッドが一定時間内にロックをウェイクアップするのを待機することです。この時間を超えると、スレッドは自動的にウェイクアップします。上。

3. Notice()

(1) は、オブジェクトのオブジェクト ロックを待機している可能性がある他のスレッドに通知するために使用されます。複数のスレッドが待機している場合、スレッドプランナは待機状態にあるスレッドをランダムに1つ選択し、それに対してnotify通知を発行し、waitさせてオブジェクトのオブジェクトロックを取得します。 (注意! ここで話しているのは waiting です。つまり、notify() メソッドの実行後、現在のスレッドはオブジェクト ロックをすぐには解放しません。つまり、wait() 状態にあるスレッドはすぐには解放しません。オブジェクトのロックを取得するには、同期されたコードが必要です。ロックは、ブロック内のコードが実行された後にのみ解放されます。)

(2) も、同期されたメソッドまたは同期されたブロック内で呼び出される必要があります。つまり、スレッドは、呼び出しの前にオブジェクトのオブジェクトレベルのロックも取得します。そうしないと、IllegalMonitorStateException がスローされます。

(3) Notice() が通知を送信しても、待機している wait() スレッドがない場合は、効果がありません。

4. NoticeAll()

(1) は、同じ共有リソース (つまり、同じロック) を待機している待機キュー内の「すべての」スレッドを待機状態から抜け出して、実行可能状態に移行させることができます。

5、

6、サスペンドデス: 「サスペンドデス」現象は、実際にはスレッドが WAITING 待機状態になることです。すべてのスレッドが待機状態になると、プログラムは機能を実行できなくなり、プロジェクト全体が停止状態になります。 この理由は次のとおりです。たとえば、複数のプロデューサと複数のコンシューマの場合、「プロデューサ」が「プロデューサ」を起動し、「コンシューマ」が「コンシューマ」を起動し、同じ種類の「コンシューマ」が起動する可能性があります。となり、スレッドは実行を継続します。この問題を解決するにはどうすればよいでしょうか?単にnotify()をnotifyAll()メソッドに変更するだけです。つまり、異種のものを一緒に起動するだけです。

7, Jave では、パイプ ストリーム (pipeStream) は、さまざまなスレッドでデータを直接送信するために使用できる特別なストリームです。 1 つのスレッドは出力パイプにデータを送信し、別のスレッドは入力パイプからデータを読み取ります。パイプを使用すると、一時ファイルなどに頼ることなく、異なるスレッド間の通信が実現されます。 JDK には、バイト ストリーム (PipedOutputStream、PipedInputStream) および文字ストリーム (PipedWriter、PipedReader) を含むスレッド間の通信を可能にする 4 つのクラスが提供されています。


public class Run {
 public static void main(String[] args) {
  try {
   WriteData writeData = new WriteData();
   ReadData readData = new ReadData();
   PipedOutputStream outputStream = new PipedOutputStream();
   PipedInputStream inputStream = new PipedInputStream();
   
   outputStream.connect(inputStream);//使两个Stream之间产生通信链接,这样才可以将数据进行输入输出

   ThreadRead threadRead = new ThreadRead(readData, inputStream);
   threadRead.start();
   Thread.sleep(1000);
   ThreadWrite threadWrite = new ThreadWrite(writeData, outputStream);
   threadWrite.start();
  } catch (IOException e) {
   e.printStackTrace();
  } catch (InterruptedException e) {
   e.printStackTrace();
  }
 }
}

3. joinメソッドの使用

1. 多くの場合、メインスレッドがサブスレッドを作成して開始し、時間のかかる大量の計算をサブスレッドで実行する場合、サブスレッドが終了する前にメインスレッドが終了することがよくあります。 。このとき、例えばサブスレッドがデータを処理し、メインスレッドがそのデータの値を取得したい場合など、メインスレッドがサブスレッドの実行完了を待って終了したい場合、 join() メソッドを使用する必要があります。

2. join() の機能は、スレッドが破棄されるのを待つことです。これにより、現在のスレッドが無期限にブロックされ、現在のスレッドのコードの実行を続行する前に、join() スレッドが破棄されるのを待ちます。 。

3. 同様に、join() メソッドは、interrupt() メソッドによって中断され、InterruptedException をスローすることができます。

4. 参加と同期の違いは何ですか?

(1) join() は内部的に wait() メソッドを使用して待機します。

(2) synchronized キーワードは、同期として「オブジェクト モニター」原理を使用します。

5. メソッド join(long) と sleep(long) の違いは何ですか?

(1) join(long) は wait(long) メソッドを使用して内部的に実装されており、wait(long) メソッドの実行後、現在のスレッドのロックが解放され、他のスレッドもこの中で同期メソッドを呼び出すことができます。糸。つまり、join(long) の後、スレッドはロックを解放し、ロック リソースを求めて他のスレッドと競合する必要があります。

(2) Thread.sleep(long) メソッドはロックを解放しません。

4. ThreadLocal クラスの使用

1. 変数値はパブリック静的変数の形式で共有できます。すべてのスレッドは同じパブリック静的変数を使用します。各スレッドに独自の共有変数を持たせたい場合、この問題を解決するにはどうすればよいでしょうか? ThreadLocal クラスは、各スレッドを独自の値にバインドする問題を解決します。ThreadLocal クラスは、各スレッドのプライベート データを格納できるボックスにたとえることができます。

2. ThreadLocal クラスには分離性があります。つまり、各スレッドは互いに影響を与えることなく自分のスレッドのデータを保存でき、取得するデータも自分のスレッドによって保存されたデータです。

5. クラス InheritableThreadLocal の使用

1. InheritableThreadLocal クラスは ThreadLocal クラスを継承するため、ThreadLocal クラスの特性を持ちます。でもそれは特別ですThreadLocal の特徴は、InheritableThreadLocal 変数の値がすべての子スレッドに自動的に渡されることですが、通常の ThreadLocal 変数は渡されないことです。さらに、このクラスの childValue メソッドをオーバーライドすることで、子スレッドは、 の任意の関数の親スレッド値として使用できます。

備考:

(1) サブスレッドとは何ですか?

Thread = new Thread(new ThreadStart(delegate{

})); に含まれるスレッドは子スレッドとみなされます。 (個人的な理解です)


(2)メインスレッドとは何ですか?

「スレッドに含まれないプログラム」を除いて、UIインターフェイスとMain関数は両方ともメインスレッドと見なすことができます。 (個人的な理解です)

以上がJavaマルチスレッドにおけるスレッド間通信の詳細説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。