実際のアルゴリズム(III):かく乱背後分析高性能キューデータ構造とアルゴリズム

実際のアルゴリズム(III):かく乱背後分析高性能キューデータ構造とアルゴリズム

かく乱は、メモリ、メッセージキューは、スレッド間のメッセージパッシングのキューです

かく乱は、高性能どうですか?基礎となるデータ構造は何に依存しますか?

循環キューに基づいて - 「生産者、消費者モデル」

消費データセンターの貯蔵容器から消費者の退避後に消費者モデル、生産者の生産データ、貯蔵容器へのデータセンター、 - このプロデューサで

データを保存センターの保管容器は、データ構造を達成するために使用何ですか?

最も一般的なデータ構造を達成するために使用されるデータはFIFOキューをサポートし、キュー・コンテナ保管センターでは、データは長い長い間、消費されてされて生成されます。アイデアを実装し、2つのキューがあり、1はキューリスト実装チェーンに基づいており、他方は異なる実装を選択するためのキュー配列の実装、さまざまなニーズに基づいています。

リストは速く動的な拡張をサポートしているため、キュー、選択リストを達成するために、事前に不確実であるキューサイズを実装無制限。あなたが有界キューを実現したい場合は、そのキューのサイズを事前に決定され、キューがデータでいっぱいであるとき、生産者は消費者がデータを支出するまで待つ必要があり、その後、生産者の位置にデータを入れるために、キュー内のスペースがあります。彼らはメモリにつながる可能性があるため、メモリキュー占有の無制限の量は、制御できないOOM(メモリー不足)エラーが増え続けています。

、削除データのプロジェクトを追加するために、非環式のキューは、データは、ほとんどの順序キューで使用されるシーンのように、単に問題を解決するためにパフォーマンスの低下、データの移動循環キューになり、選択の順番を移動操作が含まキュー循環キュー、円形キューメモリは、簡単な手段によって達成循環キューメッセージキューのプロトタイプです - キューが空のときに使用して、「生産消費者のモデルは」「キューがいっぱいになると、プロデューサーは、回転に待っています」回転待ち時間に消費した後

public class Queue {
  private Long[] data;
  private int size = 0, head = 0, tail = 0;
  public Queue(int size) {
    this.data = new Long[size];
    this.size = size;
  }

  public boolean add(Long element) {
    if ((tail + 1) % size == head) return false;
    data[tail] = element;
    tail = (tail + 1) % size;
    return true;
  }

  public Long poll() {
    if (head == tail) return null;
    long ret = data[head];
    head = (head + 1) % size;
    return ret;
  }
}

public class Producer {
  private Queue queue;
  public Producer(Queue queue) {
    this.queue = queue;
  }

  public void produce(Long data) throws InterruptedException {
    while (!queue.add(data)) {
      Thread.sleep(100);
    }
  }
}

public class Consumer {
  private Queue queue;
  public Consumer(Queue queue) {
    this.queue = queue;
  }

  public void comsume() throws InterruptedException {
    while (true) {
      Long data = queue.poll();
      if (data == null) {
        Thread.sleep(100);
      } else {
        // TODO:...消费数据的业务逻辑...
      }
    }
  }
}

「 - 消費者モデルプロデューサー」ロックベースの同時実行

キュープロデューサーに私たちだけの書き込みデータならば、消費者は、キューからデータを読み込み、同時書き込みデータキューに複数のプロデューサ、同時複数のコンシューマのキューが存在する場合、上記のコードは、問題ありません消費データは、仕事をしません

  • データは、複数の生産者がカバーできる書かれています
  • 消費者はより多くの重複データを読み出して、

2つのスレッドが同時に実行キュークラスの追加の二つのスレッド()関数に対応するキューデータに付加された、キューサイズの大きさが10、7テール電流インデックスポインティング、ヘッド添字3点、即ち、キューであると仮定自由空間、スレッドコールが追加この時間()関数、キュー値12、2つの呼び出しが追加スレッド(にデータを追加)がキュー15にデータを追加する機能もあるである、端部がデータであってもよいです正常に追加され、別のデータが上書きされる可能性があり

アドオン()関数内のキュー:

public boolean add(Long element){
if((tail + 1) % size == head) return false;
data[tail] = element;
tail =(tail + 1) % size;
return true;
}

DATA [尾]割付第3行は、わずか4つのインクリメント尾の値を整列するために、処理の割り当て動作はアトミック操作ではない、アトミック操作を中断スレッドスケジューリング機構の動作をしない指し、この動作が開始されるとそれが完了するまで実行され、中央には、それがもたらすであろう(別のスレッドに切り替えるために)どのようなコンテキストスイッチがありません:スレッド1とスレッド2同時に追加()関数を実行すると、スレッド1は、第三のラインの実装を完了するために文は、data[7](tail=7)スレッド1のスレッドの前に2行う最初の3つは、あろう、即ち尾+ 1せずに、第四のラインステートメントに行われていない前の値は、12に設定されているdata[7] = 15、すなわち、データカバレッジデータスレッドに2スレッド1

最も簡単な方法は、唯一のスレッドの実行()関数を追加し、我々はまた、CAS(比較およびスワップ比較およびスワップ)操作でロックのサイズを減少させることができる可能にする、コードをロックするために、同じ時間で

「 - 消費者モデルプロデューサー」ロックベースの同時実行

アイデアの実現 - かく乱は、キューと変更「消費者モデル、プロデューサー」であります

キューは、それがである、生産のために、追加および削除データとリードデータ、コードの追加()関数とポール()関数を、それぞれ、別の実装かく乱のアイデアを使用して、2つだけの操作をサポートデータキューを追加する前に、空き記憶ユニットがために適用するために使用することができ、連続塊状n個のメモリセルを適用して、連続したメモリ位置のセットに適用する場合、キューに追加された後続の要素が、ロックすることができず、メモリ以来このユニットは、スレッドに排他的である、メモリセルのアプリケーション・プロセスが必要とロックされています

消費者のために、連続読み取り可能な記憶ユニットの数を適用するために行く、アプリケーション・プロセスは、読み出し動作のその後の適用が完了していないロック後、ロックする必要があります

欠点である:Aプロデューサが連続したメモリ位置のセットを適用する場合、メモリセルはプロデューサインデックスBは、アプリケーション記憶部7-9に続いて、3-6を標識し、それは3-6に完全ではありませんデータを書き込む前に、データが7-9読めません

拡張概要

8つのテーブルがあると仮定ストアのユーザー情報に使用され、テーブルの各ユーザーIDフィールドのこの時間は、それ以外の場合は、繰り返し異なるテーブル間のユーザーIDの値が発生します、成長モードから生成することができない、我々はIDジェネレータを実装する必要がありますすべてのユーザーテーブルの一意のID番号を生成し、どのようにグローバルにユニークなIDを生成することが可能な同時、IDジェネレータ用の高性能、サポートを設計するには?

バルクロックを使用せず、世代IDをロックします

公開された75元の記事 ウォンの賞賛9 ビュー9161

おすすめ

転載: blog.csdn.net/ywangjiyl/article/details/104893392