序文
マルチスレッド()の理解では、同期アプリケーションに関する例を上に保持しました。彼は、生産者と消費者と言いました。私たちは、スレッドとスレッド間の通信があることを知っています。プロデューサ/コンシューマモデルが何であるかをこのブログでは、意志のディテール。
プロデューサ/コンシューマモデルとは何ですか
待機/通知メカニズムに基づいた重要なモデル、。プロデューサ/コンシューマモデルは倉庫に生産が可能な製品バッファ倉庫、として記載され、消費者は、プロデューサ/コンシューマモデルは、以下の点が懸念され、倉庫から製品を除去することができます。
- 消費者が消費することができないとき生成するプロデューサー
- 個人消費プロデューサーが生成することはできません
- 消費者が消費することができない場合、バッファは空に
- バッファがいっぱいになると、プロデューサーは生成できません
メーカー/モデルは重要なモデルとして、その点で有利です:
- デカップリング。生産者と消費者が互いに直接呼び出すことはありませんので、より多くのバッファよりも、それは、コードの変更の生産者と消費者が他に影響を与えないようにすることを、考えるのは非常に簡単ですので、実際には生産者を置くので消費者と解決の間の強い結合は、プロデューサとバッファ/コンシューマバッファ間の弱い結合となり、
- 処理能力の両方の生産者と消費者のバランスをとることにより、データ処理の全体的な速度を向上させるためには利点最も重要なプロデューサ/コンシューマモデルです。生産のプロデューサーが遅い場合、消費者は、ここでは生産者から直接データを取るが、個人消費が速く、その消費者はCPUのタイムスライスを取らなければならない場合はあそこに無駄に待っていました。プロデューサ/コンシューマモデルでは、消費者が失われたように、バッファへの2人の別体、生成されたデータのプロデューサーによって複雑になるプロデューサーと、私たちは、消費者が必要なのか、消費者も、バッファからデータを取得するだけで罰金、生産バッファがいっぱいになって、パイプの生産にはない持っていない、バッファが消費者を空にされていない、動的バランスの処理能力のプロデューサ/コンシューマ
プロデューサ/コンシューマモデルを達成するために使用待機()/(通知)
プロデューサ/コンシューマモデルはバッファを持っているので、私たち自身のバッファ行い、その後、通信の生産者と消費者は、バッファを介してです。「への値は、」バッファがいっぱいであることを示し、「バッファスペースが、値がないことを示しています」:
パブリッククラスValueObject { パブリック静的文字列値=「」; }
次のステップは、バッファが満杯である場合、次いで、もはや消費者は完全な消費者の通知を待ち、生成されていない)(待って、プロデューサー、バッファが空の場合、バッファに次に生産データ
パブリッククラスプロデューサー { プライベートオブジェクトのロック。 公共プロデューサ(オブジェクトロック) { this.lock =ロック。 } ます。public void setValueの() { 試み { 同期(ロック) { 場合(ValueObject.value.equals( "")!) lock.wait(); 文字列値=のSystem.currentTimeMillis()+ "_" + System.nanoTimeの()。 System.out.println( "設定的值是:" +値)。 ValueObject.value =値。 lock.notify(); } } キャッチ(InterruptedExceptionある電子) { E.printStackTrace()。 } } }
バッファが空の場合は同様に、消費者は、その後、何の消費、待機()待ち、予告の完成生産の待機プロデューサーはありません。バッファが空でない場合、そのデータを取得します:
パブリッククラスカスタマー { プライベートオブジェクトのロック。 公共の顧客(オブジェクトロック) { this.lock =ロック。 } 公共ボイドのgetValue() { 試み { 同期(ロック) { IF(ValueObject.value.equals( "")) lock.wait(); System.out.println( "GET的值是:" + ValueObject.value)。 ValueObject.value = ""; lock.notify(); } } キャッチ(InterruptedExceptionある電子) { e.printStackTrace(); } } }
setValue()メソッド内で)2つのスレッドが(のgetValue()メソッドおよびお客様内部でプロデューサーを呼び出す開くために、主な機能を書きます:
パブリック静的無効メイン(文字列[] args) { オブジェクトロック=新しいオブジェクト(); 最終的なプロデューサープロデューサー=新プロデューサ(ロック)。 最終顧客の顧客=新しいCustomer(ロック)。 RunnableをproducerRunnable =新しいRunnableを() { ます。public void実行() { ながら、(真) { producer.setValue(); } } }。 RunnableをcustomerRunnable =新しいRunnableを() { ます。public void実行() { ながら、(真) { customer.getValue(); } } }。 producerThread =新しいスレッド(producerRunnableを)スレッド。 CustomerThread =新しいスレッド(customerRunnableを)スレッド。 producerThread.start(); CustomerThread.start(); }
結果を見てください:
... 値に設定されます。1444025677743_162366875965845 1444025677743_162366875965845:値は、その取得し た値の設定は次のとおりです。1444025677743_162366875983541 値は、その取得:1444025677743_162366875983541 設定値を以下のとおりです。1444025677743_162366876004776 ゲット値は次のとおりです。1444025677743_162366876004776 ...
生産データと消費データは、消費者は、プロデューサ/コンシューマモデルに沿って、無制限消費することはできませんが、生産者は無制限作り出すことができない、消費者の生産ではなく、フル生産ではなく、消費空、ペアでなければなりません。生産スピードではなく、CPUのタイムスライスは、完成した消費者通知にそれを生産し続けるために、消費者を待って、この作品は、他のスレッドとの時間に使用することができます。
生産者と消費者のモデルを達成するために、)(のawait()/信号を使用して
同様に、第1のバッファゾーンを定義します。
パブリッククラスValueObject { パブリック静的文字列値=「」; }
執筆の他の種類には、単一のクラスでの生産と消費の方法:
パブリッククラスThreadDomain41はReentrantLockのを拡張 { プライベート状態条件= newCondition()。 公共無効セット() { 試み { ロック(); しばらく(!。 ""イコール(ValueObject.value)) condition.await(); ValueObject.value = "123"; System.out.println(にThread.currentThread()のgetName()+ "生产了値、値的当前值是" + ValueObject.value。)。 condition.signal(); } キャッチ(InterruptedExceptionある電子) { e.printStackTrace(); } 最後に { ロック解除()。 } } パブリック無効のget() { 試み { ロック(); 一方、( "" .equals(ValueObject.value)) condition.await(); ValueObject.value = ""; System.out.println(にThread.currentThread()のgetName()+ "消费了値、値的当前值是" + ValueObject.value。)。 condition.signal(); } キャッチ(InterruptedExceptionある電子) { e.printStackTrace(); } 最後に { アンロック()。 } } }
同様に、2つのオープンスレッドは、スレッドがセット()製造の方法は、他のスレッドは、get()メソッド消費を呼び出し呼び出します。
パブリック静的無効メイン(文字列[] args) { 最終ThreadDomain41のTD =新しいThreadDomain41()。 RunnableをproducerRunnableは新しいRunnableを()= { )(公共のボイドの実行を { のために(int型私= 0;私<Integer.MAX_VALUEで、I ++) td.set(); } }。 RunnableをcustomerRunnableは新しいRunnableを()= { )(公共のボイドの実行を { のために(int型私= 0;私<Integer.MAX_VALUEで、I ++) td.get(); } }。 ProducerThread =新しいスレッド(producerRunnableを)スレッド。 ProducerThread.setName( "プロデューサー"); ConsumerThread =新しいスレッド(customerRunnableを)スレッド。 ConsumerThread.setName( "消費者")。 ProducerThread.start(); ConsumerThread.start(); }
結果を見てください:
... プロデューサーの生産額は、現在の値が123の値である 値の消費者の消費量は、現在の値が値で 、現在の値が123の値であるプロデューサーの生産額 値の消費者の消費量は、現在の値が値である 、プロデューサーの生産額値が123の現在の値である 値、電流値の値の消費者の消費 ...
そして、同じプロデューサ/コンシューマモデルに沿って、同じ効果を達成するために、()/通知()メカニズムを待ちます
慎重な仮死う
目的のプロデューサ/コンシューマモデルは、最終的に到達処理能力の生産者と消費者のバランスを、このプロセスを達成するために、唯一の生産者と消費者を必要としません。生産者は、生産者は、消費者の複数に対応することができる、消費者が生産者に対応することができる、消費者の複数の複数に対応することができます。
仮死は、上記の3つのシナリオの下で行われました。理論的解析は、そう、コードを書いていない、問題を説明することができるようになります。コードを書くよりオープン複数のプロデューサ/コンシューマに、修飾のちょうど2つの例は非常に単純で、オープン複数のスレッドのプロデューサ/コンシューマスレッドにスレッドのプロデューサ/コンシューマの複数のスレッドを開き、スレッドスレッドをすることができます。待ち状態にすべてのスレッドが、プログラムはもはやどのようなビジネス機能を実行することをアニメーション手段、およびプロジェクト全体のプレゼント停止を一時停止。
のは、バッファが空であるため、消費者がWAITINGであり、プロデューサーとプロデューサーのBがあるとしましょう。待ち続け、その後、WAITINGでプロデューサーB、生産者Aの生産が消費者、生産者に通知され製造された製品は、消費者に知らせるべき結果は、生産者B、Bの生産者が起こされる通知、発見されたバッファがいっぱいです。これまでのところ、2つの生産者スレッドが待っている、消費者は、システム仮死待っています。
私たちが見ることができる上記の分析は、理由があるため仮死の登場で、その種の通知、非単プロデューサー/シングル・コンシューマ・シナリオは、この問題を解決するための二つの方法をとることができますされています。
)signalAllとReentrantLockの(、すべてのスレッドをウェイクアップ)のnotifyAll(と同期すべてのスレッド1を、目を覚まします
図2は、2つの定義されたReentrantLockの条件と、条件は、プロデューサ、コンシューマ表現条件、モーニングコール、それ上の信号の対応する条件()メソッドを表します
します。https://www.cnblogs.com/xrq730/p/4855663.htmlのリンクを参照してください。