[これらの事]同時生産者と消費者

ステップ1は、生産者と消費者は何ですか

生産者と消費者としても知られ、限定されたバッファリングの問題は、マルチスレッドの同期がはるかに問題の最も古典的です。二つのスレッドのための共有を使用するときに問題のシーン記述は、固定サイズのバッファのためのものです。そして、これらの2つのスレッドがいくつかのデータを入れて二つの役割、バッファゾーンの1に分割されます、我々は彼を呼び出しプロデューサーもう一つは、我々は彼に電話、バッファからデータをフェッチする責任がある消費者
ここでは、2つの問題があるでしょう、最初の問題は、生産者が、バッファへの無制限のデータを置くことはありませんバッファのサイズであるため、バッファがいっぱいになったときに、プロデューサーがストップ生産しなければならないということです。第二の問題は、バッファデータバッファが空であるときに、消費者はストップ生産しなければならない、データを取り込むための前提条件である消費者は、バッファからの無制限のデータを取得する可能性は低い、例外ではありません。
これら2つの問題は、単純なように見えるが、ピットの多くは、実際のコーディング時にまだあった、ほとんど注目は大きな間違いです。上記は、単に1つの生産者と消費者の問題であり、アプリケーションはより多くの消費と、より複雑なシーンを作り出すが発生します達成します。これらの問題の詳細については後述します。

ステップ2.なぜ、このような問題を持っています

前のセクションの内容は、私たちは生産者と消費者が何であるかを知っています。しかし、なぜこのような問題はありますか?
実際には、おそらく「問題」と語の「生産者と消費者が」より負になった場合。私は「生産者-消費者モデル」は、我々が学ぶそれらのようなコードのデザインパターンを呼び出すことを好みます。実際に、彼はマルチスレッドでのデザインパターンである、ベストプラクティスは、特定のシナリオの下で証明されています。
このパターンは、どのような効果を持っていますか?
彼の最初の利点は、分離されています。
たとえば、お持ち帰り。米国のグループが存在しない場合には、空腹まだ、確かに今そんなに弟をお持ち帰りランニングで満たされていません。あなたは、自分の料理を送信するために、通常は、上司をお持ち帰りを注文したコール。自転車に乗って、梱包箱を運ぶ、あなたの上司の野菜、野菜、調理し、その後、良いパッケージ後、と想像して、完全なセルアドレスを見つけ、そして最終的にはあなたの手に。ここではいくつかの疑問があるでしょう、まず、上司は、良い仕事をする、野菜、野菜、調理のストップを調理することは非常に簡単ではないですが、また、また、彼、乗車光が十分ではないだろう、乗りますセキュリティドアを入ることを許可されて近づいて行くために、ナナ、ナナの建物、地区に、自分の道を見つけることができます。これは理論、接続なしで、実際には、すべての機能が調理した食事を提供するボスに集中している二つのことを置くが、もし野菜が誤ってのみ食器をしないことを、彼の手にカットし、ここのボスない、返送することはできません。または赤色光を通じて急いする方法の食品配達は、お米を送って、また次に何をするために戻って来ていないだけでなく、交通警察によって停止しました。それは一緒に結合された我々のコードのすべての結果のようなものだ、2つのビジネス相互作用は、ビジネスは、ビジネスの変化は、他のビジネスの変化を取った、もう一つの問題は、問題が発生し、その後。
それはお持ち帰り弟を持っていた後、私たちは、それについて考えますか?限り、上司だけで罰金、調理に集中するよう、良い弟を奪うように。テイクアウト弟は、ユーザの手に送信されます。クックボス思考が奪うと思ったより美味しく、弟がどのように最速の配達をされ行う方法でした。機能明確な、効率が高いです。ここではお持ち帰り弟が消費者である対応する、プロデューサーとして上司することができます。
彼の第二の利点は、生産者と消費者のイコライザの能力です。
持ち帰りや移動の例。持ち帰りいくつかのリアルタイムは、単一のユーザー、ボス直ちに野菜、野菜、調理し、パッケージ化した後、次のように調理する例えば、準備することです。時間がかかり、そのようなお粥、シチューなどの料理などのために非常に長い時間がかかるかもしれません。テイクアウト兄はちょうど店遅い時間に通知の時間を費やしました。今すぐお持ち帰りシステムは、よりインテリジェントなので、最寄りのお持ち帰りから商人を通知弟なので、店は一般的に、比較的短い時間です。このシナリオでは、ボトルネックが生産能力の業務である、それはキューのピークが発生することがあります。図は次のとおりです。
image.png

そして、それはそれほど深刻になります

image.png

私たちは、非常に明確な生産者の生産は、(企業は)消費者(持ち帰り弟)消費者(部屋)速度に追いつくことができないので、この質問の理由。我々は問題が非常に明確であるので、機能を分離する必要があるので、それは生産者の生産能力を増加させる、例えば、所有者は、シェフよりもさらにいくつかを雇うことや支店を開設します。これは、容量のバランスの位置を改善するために、生産者と消費者の能力を置きます。
生産者の他の場合には、そのようないくつかの小さなスーパーマーケットとして、彼はまた、配信サービスを持って、コンシューマより高速です。彼の事は容易に利用可能になった後、単一のユーザーが終了しているので、ちょうどそれにインストールされている順番を押してください。しかし、この時間はかなり遅い外テイクアウト兄から来ています。またはアイテムは、短い時間のために準備ができているが、複雑な長い距離、道路状況の配達されます。だから、ボトルネックと弟を奪うように。

image.png

image.png

この場合、問題は、消費者の消費が拡大することを、消費者の良い番号をペース生産能力を維持することができませんでした、非常に明確です。例えば、単一のテイクアウトに頻繁に、お持ち帰り遅すぎる弟、別のお持ち帰りに転送弟に遭遇しました。同じとすることもできる生産者と消費者は、バランスのとれた生産能力を実現しています。

ステップ3.生産者、消費者のモデルを実現する方法

まあ、そんなに何が、なぜ、我々は、コードに直接何のナンセンスを生産、消費者のモデルを実現しないためにどのように言うようになりました。
まず、ボスクラスを記述します。

3.1 Boss.java(所有者)

/**
 * fshows.com
 * Copyright (C) 2013-2019 All Rights Reserved.
 */
package cn.coder4j.study.example.thread;

import java.util.LinkedList;

/**
 * 老板
 * @author buhao
 * @version Boss.java, v 0.1 2019-11-09 15:09 buhao
 */
public class Boss implements Runnable {
    /**
     * 最大生产数量
     */
    public static final int MAX_NUM = 5;
    /**
     * 桌子
     */
    private LinkedList<String> tables;

    public Boss(LinkedList<String> tables) {
        this.tables = tables;
    }

    @Override
    public void run() {
        // 注意点1
        while (true){
            synchronized (this.tables){
                // 注意点2
                while (tables.size() == MAX_NUM){
                    System.out.println("通知外卖小哥取餐");
                    // 注意点3
                    this.tables.notifyAll();
                    try {
                        System.out.println("老板开始休息了");
                        this.tables.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                String goods = "牛肉面" + tables.size();
                System.out.println("老板做了一碗" + goods);
                tables.addLast(goods);
            }
        }
    }
}

その後、我々は弟のお持ち帰りカテゴリを書きますが、恥ずかしいが英語で書くためにどのように弟のノウハウを奪うしないことが判明され、私は結果は次の通りです確認し
image.png
、この兄弟はいつも奇妙な感じが、私はあまり読んでいて、彼は私にはわからない、嘘をつきましたこの権利を使用しています。ある場合は、大きな英語神は正しく書く方法に関するメッセージに返信することができます。

3.2 TakeawayBrother.java(持ち帰り弟)

/**
 * fshows.com
 * Copyright (C) 2013-2019 All Rights Reserved.
 */
package cn.coder4j.study.example.thread;

import java.util.LinkedList;

/**
 * 外卖小哥
 * @author buhao
 * @version TakeawayBrother.java, v 0.1 2019-11-09 15:14 buhao
 */
public class TakeawayBrother implements Runnable {

    private LinkedList<String> tables;

    public TakeawayBrother(LinkedList<String> tables) {
        this.tables = tables;
    }

    @Override
    public void run() {
        while (true){
            synchronized (this.tables){
                while (this.tables == null || this.tables.size() == 0){
                    System.out.println("催老板赶快做外卖");
                    this.tables.notifyAll();
                    try {
                        System.out.println("一边玩手机一边等外卖");
                        this.tables.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                String goods = tables.removeFirst();
                System.out.println("外卖小哥取餐了" + goods);
            }
        }
    }
}

弟を奪うために、一般的に外国人の所有者に販売に行く場所は、常にそこにあるイベントは、お店であり、最終的に我々は店のクラスのバーのシーンを追加します

3.3 StoreContext.java(ショップ)

/**
 * fshows.com
 * Copyright (C) 2013-2019 All Rights Reserved.
 */
package cn.coder4j.study.example.thread;

import java.util.LinkedList;

/**
 * 店铺场景
 * @author buhao
 * @version StoreContext.java, v 0.1 2019-11-09 15:28 buhao
 */
public class StoreContext {

    public static void main(String[] args) {
        // 先创建一张用于存放外卖的桌子
        LinkedList<String> tables = new LinkedList<>();
        // 再创建一个老板
        Boss boss = new Boss(tables);
        // 最后创建一个外卖小哥
        TakeawayBrother takeawayBrother = new TakeawayBrother(tables);
        // 创建线程对象
        Thread bossThread = new Thread(boss);
        Thread takeawayBrotherThread = new Thread(takeawayBrother);
        // 运行线程
        bossThread.start();
        takeawayBrotherThread.start();
    }
}

3.4オペレーティング結果

老板做了一碗牛肉面0
老板做了一碗牛肉面1
老板做了一碗牛肉面2
老板做了一碗牛肉面3
老板做了一碗牛肉面4
通知外卖小哥取餐
老板开始休息了
外卖小哥取餐了牛肉面0
外卖小哥取餐了牛肉面1
外卖小哥取餐了牛肉面2
外卖小哥取餐了牛肉面3
外卖小哥取餐了牛肉面4
催老板赶快做外卖
一边玩手机一边等外卖
老板做了一碗牛肉面0
老板做了一碗牛肉面1
老板做了一碗牛肉面2
老板做了一碗牛肉面3
老板做了一碗牛肉面4
通知外卖小哥取餐
老板开始休息了
外卖小哥取餐了牛肉面0
外卖小哥取餐了牛肉面1
外卖小哥取餐了牛肉面2
外卖小哥取餐了牛肉面3
外卖小哥取餐了牛肉面4
催老板赶快做外卖
一边玩手机一边等外卖
..........

ステップ4コード説明

まず、上記のコードは、単一の消費の単一生産の基本的な例です。あなたは、いくつかの上司やtakeawayBrother、それを作成するために、それ以上のものをより多くの消費を生成します。
そして、スレッドの作成のために、上記を参照している場合かわからない、何も言うことは、スレッドを作成するだけで、基本的なロジックのようなシーンを買い物[それらのもの] 3通りの方法で作成された同時実行スレッドこの記事ではそれらを繰り返すことはしません。また、観察コード、生産者と消費者は単に預金を取る、非常に類似したコードを見ることができます。ここでは例として、プロデューサーです。
彼のクラスボスプロパティで最初は1つがMAX_NUMテーブルで、二つの部材を持っています。私たちは、「固定サイズバッファ、」それの先頭に言及している覚えていますか?ここでは、ここで我々は5セットされ、対応するMAX_NUM「固定サイズ」の言葉です。彼の重要性は、それほど大きな調理することができない上司で、決して、ピーク時にある程度の時間が先に少しを行うやって起動する時には通常、単一の点で、朝から晩まで停止したが、彼は唯一の食品テーブルを置きます缶の完全なそしてません。テーブルには、単語を「バッファ」に対応することになります。ボス完成料理はいつも来て敷設する場所及びその他の持ち帰り弟を持っており、それを収集し、バッファは、食品のテーブルを置くことです。
その後、我々は、私はコード内のいくつかの注意点をマークし、コードのロジックを見に行きました。
音符の最初の点は、一方の最外層です。彼らはその後、タスクコード出口の終了後、ながら書いていないので、これは、マルチスレッドの一般的な文言です。我々は通常のビジネスの実際のビジネスを解決するにはしばらくを追加するので、実行し続けたいです。
なお、第2の点一方(tables.size()== MAX_NUM) 。条件を判断すると、テーブルの上に現在の取出しが既に上限に達していない、それはコードブロックしながら、コンテンツになった場合、最初の通知(のnotifyAll)テイクアウト弟はお持ち帰りを得ることができるかを決定することである一方、最初の意味情報のこの比較的少ない量、その後、我々は(待機)から回復、またはダウンした後、し続けることができます。学生のための生産と消費のモデルとの最初の接触は、ここでのポイントを間違えやすいですしながら、場合書かれていることです。生産の条件は現在のバッファを満たすためにかどうかを決定するためにのみ、それ自体があるため。実際には、文法やロジックに問題はありませんが、マルチスレッドに表示されますスプリアスウェイクアップ問題。例えば、今、2人のローカル生産者が呼び出し待機しているがあります。突然、消費者の完成消費者データへのスレッド、および生成するために、すべての生産者に通知するには、2人の生産者がメッセージを受信しているが、唯一のプロデューサーロックを取得するために、彼は製造後、ロックが解除され、生産に行ってきましたちょうどこれが事実であるかのように、すでに判断されている、と判断しないだろうが、明らかに別のスレッドがタスクを完了した、場合、彼は今ある、そして下るにロックを取得するために、別のプロデューサーのニュースを受けていました条件を満たしていません。次に問題となる下ります。これは一方で置き換えるときに、彼はその後、このように、この問題の偽のきっかけを避け、それは満たしていないのを待ち、その後いったん決定します目が覚めました。
注三点this.tables.notifyAll()という。あなたの2番目の質問では、我々は言うかもしれないが、問題は、我々はまた、原因2台の生産に気づくので、Javaは、目を覚ます覚醒のnotifyAllメソッドは、すべてのスレッドを利用しますないのはなぜ単一のスレッドのための方法を通知しています。通知再開されたスレッドがあるためであるランダムあなたは生産者が、消費者かもしれウェイクかもしれないことを意味し、。たとえば、あなたがプロデューサーです、あなたは十分を作る、あなたが消費者の目を覚ますしたいが、残念ながら、あなたは別のプロデューサに目を覚ますと、別のプロデューサーは、目が覚めたと食器が行われた生産ならば、彼らは、睡眠に行ってきました誰がプロデューサーで、プログラムが入ります目覚めましたアニメーションの一時停止状態を、消費者が待機状態に常にあります。

他の

1.プロジェクトコード

紙面の都合で、全てではないなどの問題が発生する可能性があり、コードを終えたgithubのソースコードを表示します。

2.参照リンク

  1. 生産者と消費者[WIKI]
  2. プロデューサ/コンシューマモデル:のJava 14をマルチスレッド
  3. 記事なので、あなたは完全にプロデューサーを理解していること - 消費者問題

image.png

image.png

おすすめ

転載: www.cnblogs.com/kiwifly/p/11826766.html