まず、事前にコースの問題
私たちは、CPUリソースが限られている、知っている、処理スピードのタスクは、積極的にスレッドの数と相関していたが直線的ではありません。代わりに、あまりにも多くのスレッドは、抗⽽頻繁な切り替えCPUの処理性能につながることができます。
そのため、スレッドプールのサイズは、一般的に、事前に設定する機能とハードウェア環境の課題に対処するために考えられています。
アイドルスレッドプールリソースが存在しない場合、我々は、一定の大きさにスレッドプールのスレッドを要求すると、この時間スレッドプールこの要求に対処する方法?または拒否要求は要求をキューに入れていますか?
様々な治療戦略は、それを達成する方法ですか?
実際には、これらの質問は、その基礎となるデータ構造の内容は、我々は今日、キュー(待ち行列)を学ばなければならないこと、複雑されていません。
第二に、どのように「キュー」を理解するには?
1.キューとは何ですか?
あなたはまず、最初に買いに来る、チケットのキューアップと考えることができ、その後、人々は唯一の終わりに立つことができ、キューをジャンプすることはできません。高度な、最初のうちは、これは典型的な「キュー」です。
2、キューのサポートの操作
1、エンキューエンキュー()、データキュー尾に入れ、
2、デキューデキュー()、キューの先頭から取られた要素。
3、キューのシナリオ
; 1、高性能キューかく乱、Linuxのリングバッファは、複雑なサイクルのキューを使用している
Javaの同時契約を使用して、2及び公正ArrayBlockingQueueロックを達成します。
キュースタックとも限られた線形動作し、テーブルのようなデータ構造
第三に、キューの順序とキューチェーン
どのキューに1、
スタックは、キューが実装するためのアレイを使用することができますように、あなたも達成するために、リストを使用することができます。スタックの配列の順序と呼ばれるスタックを実装し、スタックとスタックは、リンクリストの実装のチェーンと呼ばれます。また、キューを実装配列の順序は、キューと呼ばれる
キューのチェーンリンクリストの実装は、キュー・チェーンと呼ばれています。
2、キューチェーン
図1に示すように、コードに実装キューのアレイ
//キューで実装アレイ パブリッククラスArrayQueue { //配列:商品、配列サイズ:N- プライベート文字列[]アイテム、 プライベートint型N- = 0; //ヘッドHOLは上付き文字を表し、尾テール添字が表す プライベートINT = 0ヘッド、 専用テールINT = 0; //サイズ容量のアレイ適用 公共ArrayQueue(INT容量){ 商品=新しい新しいString [容量]; N容量=; } //エンキュー パブリックブールエンキュー(文字列の項目) { //尾== nはキューが満杯であることを示す場合には 偽にIF(尾== N)リターン; 商品[尾] =項目; ++尾、 真への復帰; } //デキュー パブリック文字列デキュー(){ //ヘッド==テールキューが空であることを示している場合 IF(ヘッド==尾)のリターンはnull; //は、より明確に確認するために、学生に別の言語を与えるために-書くために別の行に操作を 文字列RET =アイテム[ヘッド]を; ++ヘッドと、 リターンRETを; } }
2、アイデアの実現
キューは、二つのポインタが必要です。
- ヘッドポインタキューヘッドがあります。
- テールは、テールへのポインタです。
あなたは理解するには、以下のこの絵を組み合わせることができます。場合、B、C、Dを順次添字の次のキュー位置0,4標識位置までテール・ポインタに、ヘッドポインタポイントをキューイングされます。
私たちは二度デキュー操作が呼び出されると、次の位置にキューヘッドポインタは2は、テールポインタはまだインデックス位置4を指している、ラベルされました。
図2に示すように、データ移動
常にエンキュー、デキュー操作、頭、尾と連続して後方に移動されます。右端にすると尾に移動するには、空き領域が配列であっても、データがキューに追加していくことはできません。どのようにこの問題は、それを解決しますか?
しかし、データの配列の添字0の削除などたびにデキュー動作を全体キューからデータを移動するためには、この操作の時間計算量は、元のO(1)からデキューされるであろうO(Nなります)。あなたは少し最適化することができませんか?
3、データ移動の問題が原因?どのように最適化するには?
実際には、我々はチームの時にデータを移動することはできません。空き領域が存在しない場合、および
私達はちょうどチームに時間を必要とし、その後、トリガーに移動運用データを集中します。この考え方では、チーム機能デキュー()は変更されないまま、
私たちは、チームわずかに変更された機能のエンキュー()の実装に見て、あなただけで簡単に問題を解決することができます。以下は、特定のコードです:
//エンキュー操作、尾に項目 エンキュー(文字列の項目){ブールパブリック キュースペースの終わりを示すことなく// == N-テイル (== N-尾){IF // && Nテールヘッド== == 0は、キュー全体の塗りつぶしを表す IF(ヘッド== 0)偽に戻り; //データ移行 のための(INT I =ヘッドと、I <尾; I ++){ 項目[I-頭] =項目を[I] ; } 新しく頭と尾移動//終了後に更新 尾を- =ヘッドと、 ヘッド= 0; } アイテム[尾] =項目; ++尾、 真のリターン; }
私たちは、チームに新しいデータが、我々は、間のデータの最後尾に頭尾頭の配列に一体的に0を移動することができます場合は、キューのテール・ポインタが、一番右の列に移動されたコードからご覧ください場所。
4、チェーンキュー
ヘッドポインタとテールポインタ:リストベースの実現、我々はまた、二つのポインタを必要としています。彼らは、最初のノードと最後のリンクリストのノードを指します。
図示のように:
- 入队时、tail->次= new_node、尾= tail->次。
- とき、チーム、=頭部>次の頭。
私はあなたがそれを達成しようとし、右側に書かれた確認するために、達成するために私を比較GitHubの上でのコードの下に行くことができ、GitHubの上の特定のコードになります。
第四に、循環キュー
1.何が円形キューです
円形キュー名は、リングのように見えることを意味しています。もともと配列は最後まで始めている直線です。今、私たちはリングに引っ張って、最後に終止符を打ちます。私は図を描き、あなたは直感的に感じることができます。
私たちは見ることができます:
- 図中のキューの大きさ。8、現在のヘッド= 4、尾= 7。チームに新しい要素があるとき、私たちはインデックスをつけ、それぞれ、7です。
- しかし、この時間は、我々は尾が8で更新されませんが、添字0の位置に、リングの後にそれを1つずつ移動します。
- 要素bがチームに再びがある場合、我々はインデックス位置0、および尾プラス1更新1に置かBします。
したがって、連続的にキューに入れ、bの後、循環キューの要素には、次のようになります:
良いチーム空の決意条件を決定するために2、
書き込みバグのないコードその実装円形キューに、私が思うに、最も重要なは、空の判定条件の完全な優れたチームとチームを決定することです。
- 非円形キューの実装のアレイでは、チームはその完全な尾== nは、空の判断のチームヘッド==テールことを決定しました。
- その循環キューのために、どのようにチームを決定するために、チームは完全な、それを空にされますか?
- キューが空である、決意条件遺骨は==尾を頭。しかし、キュー満杯状態がやや複雑に決定されます。
私はキューの図は、あなたがどのような法律を要約してみてください、で見ることができいっぱいです描きました:
3、決意条件の完全なチームを決定します。
I絵画の完全なチームの場合のように図形、尾部= 3、ヘッド= 4、N = 8、
そうルールを要約することである:(1 + 3)%8 = 4。マルチマップの完全なチームを描き、あなたはそのチームがいっぱいになるでしょう、(尾+ 1)%、N =頭を。
あなたは今までにキューが満杯になったとき、尾の場所に数字のポイントは、実際にデータが格納されていないあることに気づきました。したがって、配列の循環キュー消耗収納スペース。
あなたはまだそれはあなたがそれをコーディング示すだろうか、理解していない場合の話では、安いです。
CircularQueueクラス{公共 //配列:商品、配列サイズ:N- プライベート文字列[]アイテム、 プライベートN-INT = 0; //ヘッドHOLは上付き文字を表す、テール添字は尾表す = 0プライベートヘッドINTを、 プライベートINTテール= 0; //のサイズ容量のアレイ適用 公共CircularQueue(INT容量){ 商品=新しい新しいString [容量]; N容量=; } //エンキュー パブリックブールエンキュー(項目文字列が){ //キューが一杯になった 場合((+尾1)==%のn-ヘッド。)偽に戻り、 アイテム[尾] =項目; 尾=(。+尾1)N-%; 真への復帰; } //デキュー パブリック文字列デキュー(){ //ヘッド場合==テールキューが空であることを示し、 IF(=ヘッド=尾)のリターンはnull; 文字列RET =項目[ヘッド]。 ヘッド=(ヘッド+ 1)%N。 RETを返します。 } }
ファイブブロッキングキューと同時キュー
1.キューをブロックしている何
キューをブロックすると、実際にキューブロッキング操作の増加に基づいています。
- キューが空の場合簡単に言えば、チームの先頭からのテイクデータがブロックされます。好ましくは、この時点でのデータを持つキューまでのデータは返されませんされるので、
- キューがいっぱいの場合、キューはデータを挿入する前にアイドル位置になるまで、操作のデータを挿入し、それがブロックされ、その後、再び。
「 - 消費者モデルプロデューサー」あなたは、その上の定義を発見したはずです!「 - 消費者モデルプロデューサー」はい、我々はブロッキングキュー、簡単に使用することができます!
2、ブロックキューと「プロデューサー - 消費者モデル」」
このブロックキューベースの実装「プロデューサー - 消費者モデル」、効率的に生産と消費率を調整することができます。
- 速すぎて本番データの「プロデューサー」のスピード、消費への「消費者」の時間は、データを格納するためのキューがすぐにいっぱいとき。
- この時間は、生産者は「消費者」消費者データになるまでブロックします、「プロデューサー」ウェイクアップされ続ける「生産を。」
- そして、キューをブロックに基づいて、ということだけではなく、我々はまた、「プロデューサー」と「消費者」の数を調整することにより、処理効率をデータを提出することができます。
- 例えば、前の例では、我々はに対処するために、「消費者」以上のものを設定することができます「プロデューサー。」
3、同時キュー:スレッドセーフなキューにそれを実装する方法は?
同時に、キューを操作する以前の私たちは、マルチスレッド状況でキューを遮断について話しました、複数のスレッドがされ、その後どのようにスレッドセーフなキューそれを実装するために、この時間は、スレッドの安全性の問題が存在するのだろうか?
- 私たちは、スレッドセーフなキューの同時キューと呼ばれます。最も簡単な実装では、()、()に直接エンキューでロックにデキューではありません
- しかし、並行処理ロック粒度の大きい程度は一度だけデポジットを可能にする、比較的低いこと又は操作をフェッチします。
- 確かに、円形キュー配列、CASアトミック操作に基づいて、それは非常に効率的な同時キューを実現することができます。これはまた、より広く循環キューキューチェーンチェーンの理由です。
実際の説教かく乱時間では、私は詳細に同時キューの適用を話します。
六、答えが始まります
1、2つの治療戦略
私たちは、一般的に2つの治療戦略を持っています。第1のアプローチは、非ブロッキング、直接タスク要求を拒否です。
別のアプローチがブロックされ、要求がアイドル状態のスレッドがあるまで、撮影したキューに入れられた要求が処理を続け、キューイングされます。
その要求は、それを格納する方法をキューに入れられていますか?
このキュー・データ構造がキューに入れられた要求を格納するのに非常に適しているように、我々は、最初のサーブ、高度、各キューの要求の公平な扱いをしたいです。我々が言ったように、これらの2つの実装に基づいて、リンクされたリストや配列に基づいてキューがあります。
キューに入れられた要求のための両方の実装は、それがどのような違いを生むのでしょうか?
2.違いキューリストと配列は何基づいています
方法のリストに基づいて:
サポート無制限のライン有界キュー(アンバウンド形式のキュー)を達成することができますが、あまりにも多くの要求を生じ得るがキューイングされている
要求応答処理時間が長すぎます。だから、キューリストを達成するために、限られたスレッド・プールに基づいて、システムのより敏感な応答時間のために適切ではありません。
アレイベースの実装有界キュー(有界キュー):
- キューの限られたサイズなので、スレッドプールは、要求をキューに入れられたキューのサイズを超えて、次の要求は、拒否されます
- このように、応答時間に敏感なシステムでは、比較的より合理的。
- しかし、キューサイズの合理的なセットは、非常に豪華です。
- キューキューアップは、システムリソース、最大化の性能をフルに活用することができませんすぎる、あまりにも多くの保留中の要求には小さすぎるリードです。
3、他のシナリオキュー
前述したアプリケーションキューの要求に加えて、スレッドプールのシーン外側をキューに登録:
- キューは、任意の有限のリソースプールに適用することができ、
- リクエストキュー、
- データベース接続プールなど。
空きリソースがない場合に実際には、ほとんどの限られた資源のシナリオのために、要求キュー「キュー」は、このデータ構造によって、基本的に実装することができます。
VII概要
今日は非常に類似したスタックデータ構造キューと⼀種について話しました。キューについては、次の、このセクションがない問題をマスターすることができます。
- 最大の特徴は、主に2つの操作は、エンキューおよびデキューされ、FIFOキューです。同じスタックでは、両方の配列を達成するために使用することができ、あなたも達成するために、リストを使用することができます。
- キューと呼ばれる配列を達成するため、
- リストでキューを達成するためのチェーンと呼ばれます。特定のキューには、円形のリングのように見えます。
- データ移動の問題を解決するために、データ移動操作があるだろう配列キューでは、リング状の円形キューに必要です。
循環キューは、私たちの祭りの焦点です。道具循環キューその書き込みバグのないコードに、キーが空の判定条件、あなたが書くことができるようにしたい特定のコードの完全な良いチームとチームを決定することです。
また、我々はまた、慣れるADVANCEDキュー構造の種類について話す、キューの同時ブロッキングキュー、キューはまだ、このデータ構造の底部が、他の多くの追加機能です。キューをブロックすると、チームの中にある
ブロックできるチームを操作し、同時キューはマルチスレッドセーフなキューを操作しています。
八、放課後の思考
このプールの構造は、要求をキューイングに使用されるスレッドプールに加えて、あなたはまた、同様のセル構造やシーンが要求それにキューを使用するかわから1.?
- 操作カードの送信では、処理のために循環キューを経由してデータパケット、Linuxカーネルのプロトコル・スタックを受け取ります。
- キュー・データベースに作用するアレイベースのシーケンスを使用しています
- アレイの接続プールRedisの用途キューベースの順序で
2.今日はロックフリー同時キューを達成するためにどのように同時キューについて話しました、オンラインディスカッションがたくさんあります。この問題では、どのようにそれを見ていますか?
- RUCのLinuxカーネルモードとユーザーモードの共有データへのロックフリー同時アクセスを実現urcu、それは少しシーンを読み書きするのに最適です。
- その核となるアイデアは、重複コピーがリストデータ、原子鎖ポインタの動き、真のロック操作をリンクされています。