1、基本的な考え方
1、共有リソース
アクセス(読み取り又は書き込み)が同じリソースのコピーに複数のスレッドは、リソースが共有リソースとして知られています。複数のスレッドがデータにアクセスすることを確保するための方法と同じである、データ同期やリソースの同期と呼ばれています。
図2に示すように、スレッド通信
また、内部プロセス通信として知られているスレッド間通信、およびネットワーク通信処理の異なる通信、複数のスレッドが時間のリソースへの相互排他的アクセスを達成するために、それはお互いに信号を送ります。
2、同期、非同期、ブロッキング、非ブロッキング
同期および非同期の方法は、ブロッキングとノンブロッキングが他のものを完了するために、結果を待つかどうかで、結果を取得することです。
クライアントのデータを待機する同期ブロック(BIO)は、読まれた、またクライアントをブロックし、必要なデータがあるか否かを判断します。
同期非ブロッキング(NIO)は、あなたが読み込まれたクライアントのデータを待つ必要がありますが、ポーリングデータを経由して、クライアントが他のことを行うことができますかどうかを判断します。
非同期ブロック、休止状態の待機中のコールバック通知の結果、CPUののを待っています。
非同期読み取り操作を完了するために(AIO)非ブロック、オペレーティングシステム、リード完了通知コールバックは、クライアントのデータをポーリングするスレッドプールの方法を使用して、あなたは他のことを行うことができます。
同時に、単一のCPUは、複数のタスクを処理しますが、同時に実行で1つのタスクのみできます。
、複数のCPUで同じリアルタイム操作を実行するための並列複数のタスク。
2、ライフサイクル
3、デーモンスレッド
一般的には、新しいスレッド作成したスレッドを使用しても、ユーザスレッドとして知られている非デーモンスレッド、あります。道を守るために実行する前に、(真)は、setdaemonを呼び出す、ということです。デーモンスレッド、単にユーザスレッドにサービスを提供するため、すべてのユーザー・スレッドの実行が終了したら、保護者が最後になります。逆に、限り、非デーモンスレッドが存在するとして、その後、ガードは、スレッドを終了しないでしょう。
デーモンスレッドシナリオ:ガベージコレクション、心拍検出、スペルチェックスレッド
com.vimパッケージ;
輸入java.util.concurrent.TimeUnit。
パブリッククラスアプリの{
公共の静的な無効メイン(文字列[]引数)が例外をスロー{
スレッドt =新しいスレッド(() - > {
一方、(TRUE){
{試します
TimeUnit.SECONDS.sleep(1)。
System.out.println( "......");
}キャッチ(例外e){
e.printStackTrace();
}
}
});
// tはのみ終了します親プロセスの終了で、ここで設定します
t.setDaemon(真の);
t.start();
TimeUnit.SECONDS.sleep(5)。
System.out.println( "メインは終わりました!");
}
}
4、スレッド収率、睡眠
降伏した後、RUNNING状態から実行可能状態にスレッドの譲歩と呼ばれる、RUNNING状態に、執行力をつかむために再び切り替えることが可能です。
睡眠は、スレッドをブロックすることができBLOCKED状態に入り、これを懸濁し、CPUのように、唯一の遮断時間は、最大で、必ずしも直ちにCPUを実行する権利を取得しない、実行可能状態に入ります。
睡眠(0)の役割は、オペレーティング・システム、すぐに再CPUの競争、まだ現在のスレッドのCPU制御を取得競争の結果、おそらく一度トリガされ、別のスレッドで置き換えることができるには、CPUの制御を取得します。
com.vimパッケージ;
パブリッククラスアプリの{
公共の静的な無効メイン(文字列[]引数)が例外をスロー{
新しいThread(() - > {
{試します
一方、(TRUE){
Thread.sleep(0)。
}
}キャッチ(例外e){
e.printStackTrace();
}
})。開始();
}
}
5、スレッドの割り込み
、睡眠、待ってブロックされた状態に現在のスレッドに参加し、ブロックされた中断することができ、割り込み、単に渋滞状態を提示することを意図しています。InterruptException現在のスレッドがシグナル通知として例外がスローされます。この通知は、フラグがtrueに設定されますが、ステータスビットのブロッキング状態のために中断falseにリセットされる中断されます。thread.isInterrupted()によって判断、もちろん、ブロッキング状態では、このように方法の結果に影響を及ぼし、除去されます。
パッケージcom.sample.modules.test。
輸入java.util.concurrent.TimeUnit。
パブリッククラスTest {
//スレッドを中断し、割り込みビット真
パブリック静的ボイドTEST1は(){例外をスロー
スレッドt =新しいスレッド(() - > {
// 2.割り込みフラグの現在の状態が真でゲット
System.out.println(にThread.currentThread()isInterruptedを()。)。
});
t.start();
// 1.割り込みスレッド
t.interrupt();
TimeUnit.MINUTES.sleep(4)。
}
//スレッドを中断し、少し偽の中断
パブリック静的ボイドTEST2は(){例外をスロー
スレッドt =新しいスレッド(() - > {
2 //割り込みクリアビット
Thread.interrupted();
3 //現在の割り込みフラグが偽でゲット
System.out.println(にThread.currentThread()isInterruptedを()。)。
});
t.start();
// 1.割り込みスレッド
t.interrupt();
TimeUnit.MINUTES.sleep(4)。
}
//スレッドを中断し、少し偽の中断
パブリック静的ボイドTEST3は(){例外をスロー
スレッドt =新しいスレッド(() - > {
// 2は、原因に参加、割り込み待機、睡眠をブロック
{試します
TimeUnit.SECONDS.sleep(5)。
}キャッチ(InterruptedExceptionある電子){
System.out.println( "私は、中断しています");
}
3 //現在の割り込みフラグが偽でゲット
System.out.println(にThread.currentThread()isInterruptedを()。)。
});
t.start();
// 1.割り込みスレッド
t.interrupt();
TimeUnit.MINUTES.sleep(4)。
}
//は、ブロッキングの前に結果を中断:、偽真、私は中断しています、偽
パブリック静的ボイドTEST4(){
Thread.interrupted();
System.out.println( "割り込みフラグ:" +にThread.currentThread()isInterruptedを())。
Thread.currentThread()の割り込み();
System.out.println( "割り込みフラグ:" +にThread.currentThread()isInterruptedを())。
{試します
TimeUnit.SECONDS.sleep(1)。
}キャッチ(InterruptedExceptionある電子){
System.out.println( "私は、中断しています");
}
System.out.println( "割り込みフラグ:" +にThread.currentThread()isInterruptedを())。
}
公共の静的な無効メイン(文字列[]引数)が例外をスロー{
TEST3();
}
}
6、スレッドが参加します
親スレッドは実際にあなたが作ることができますので、もちろん、各呼び出しは、(0)メソッドサイクルを待つために、子どもの生存状況を判断するために糸ループ、ロックを追加した、(0)参加呼び出し、子スレッドは、joinメソッドを呼び出します他のスレッドも(0)メソッドに参加入力することができます。
//現在の方法は、ロックされていません
公共最終ボイドは、(参加)InterruptedExceptionあるが{スロー
(0)参加します。
} 無錫はhttps://yyk.familydoctor.com.cn/20612/男性の病院を参照してください
//このメソッドがロックされ、その後、他のスレッドは、(参加を入力することができます)ではなく、(0)参加へ
//は常にこのようにロックを解除し、(0)待機を呼び出し、生きているスレッドかどうかを確認し、他のスレッドが参加を入力することができます(0)、つまり、あなたがスレッドを待っている複数のスレッドを持つことができ、完成です
//スレッドが生存していないならば、それはjoin()メソッドに戻ります、呼び出し元のスレッドが実行を継続することができます
公共の最終同期ボイドが{(長いミリ秒)に参加します
IF(ミリ== 0){
一方(のisAlive()){
(0)待ちます。
}
}
}
7、スレッドの通知は、通知、待ちます
両方を使用してObjectクラスから派生これらの2つの方法、。この方法は、メソッドをオブジェクトに属し、あなたがオブジェクトのモニターロックを呼び出す前に取得する必要があります待って、コールの後、そのオブジェクトに関連するwaitsetを入力し、ウェイクを知らせる使用して他のスレッドを待機するオブジェクトのモニターロックを解除します。
典型的な生産と消費のシナリオ:
現在の倉庫が満杯になった場合、ロックを解除待っ使用、ブロックされたwaitsetを入力し、財の生産における生産現在の倉庫が満杯でない場合、倉庫(アイソクロナスリソース)が、ロックされていたが、その後、消費者に通知のnotifyAll使用するように製品を追加します通知を待つのnotifyAll。
現在の倉庫が空の場合は、ロックを解除待つwaitsetを入力を使用し、消費者、消費がプロデューサーに通知のnotifyAll使用し、製品を取る、その後、現在の倉庫の製品ならばロックする倉庫(同期リソース)、倉庫に来ました待機のnotifyAll通知を遮断します。
notifyAllが来ると、すべての生産者と消費者、倉庫を取得するための鍵を持ってする機会のために、競争は再び多くの決定ロジックになります。
8違い、待って中に眠ります
一般的には:
ブロックされた状態にスレッド、割り込み中断することができます。
違い:
待機オブジェクトは、睡眠がユニークなスレッドである、があります。
同期して実行する必要がありますプロセスを待って、睡眠が必要。
同期方法の睡眠場合は、ロックを解除します待って、ロックを解除しません。
9、例外処理スレッド
パッケージcom.sample.modules.test。
パブリッククラスTest {
公共の静的な無効メイン(文字列[]引数)が例外をスロー{
スレッドt =新しいスレッド(() - > {
int型I = 1/0;
});
t.setUncaughtExceptionHandler((スレッド、E) - > {
System.out.println( "例外...");
});
t.start();
}
}
10、コンピュータのメモリモデルとJavaのメモリモデル
原理遡及:命令実行時のCPU、メインメモリ(RAM)からのデータ、速度等の両方が深刻ではないために、キャッシュ・バッファとの間で発生し、一般的にL1、L2、含むCPUコア当たりのL3キャッシュに分かれ共有L1、L2およびL3キャッシュのセット。
キャッシュコヒーレンシ問題:コンピューティングタスクを複数のプロセッサは、その後、キャッシュに書き込まれ、その後、計算、ローカルキャッシュに、メインメモリから削除各CPU変数、同一の主記憶領域を参照キャッシュは、メインメモリにフラッシュ。
私はキャッシュにメインメモリを読みます
私がする++します
ライトバックキャッシュ結果
バックメインメモリにキャッシュを更新します。
キャッシュコヒーレンシプロトコル:共有変数が見つかった場合、キャッシュ内のCPU動作データは、その後、書き込み時に、それは他のCPUを実行し、無効化された可変CPUキャッシュラインの他に信号を送ります変数の読み取りは、あなたが読んでメインメモリに移動する必要がある場合。
比較すると、コンピュータのメモリモデル、Javaのメモリモデル:スレッド== CPU、ワーキングメモリ== CPUキャッシュ、メインメモリ==メインメモリ。
12、並行プログラミングの三の大特徴
アトミック、複数の操作は、いずれかのすべての実行されるか、まったく実行されません。
可視性、共有変数のスレッドは、その後、他のスレッドがすぐに修正後の値を見ることができ、変更されています。
秩序、オーダーの実行中のプログラム・コード。
13、synchronizedキーワード
synchronizedキーワードは、共有変数、つまり同じ時間に相互に排他的アクセスを確保するために、ロックする機構を提供し、1つのスレッドのみリソースへのアクセスを同期します。
メモリの利用規約、モニターが入る前に、いずれかのスレッドがメインメモリからデータを取得しなければならないことを確実にするために、出口2つのJVMコマンドを入力して、監視モニターは、モニター終了後、あなたは、メインメモリに更新された値を更新する必要があります。モニターがexitコマンドで指示を入力する前にJVMコマンド、厳格なコンプライアンスはhappends-前の原則の両方が、そこに存在している必要があります。
同期リソースへの排他的アクセスのためのキーワード、非常に効果的な、しかし他のスレッドを監視するために取得していない、進めることができないブロック解除どのくらいのブロッキング、最終的には、これらは不明です。この目的を達成するために、Javaは明示的に私たちのためにロックする他のソリューションを提供しています。ReentrantLockのよう。
14、AQS
排他的
#取得します
1、成功した直後に戻るリソースを獲得しようと、それが失敗した場合、排他的なノードを作成して使用してCASはスピン状態に入るようにキューの最後に追加しました
最初のノードがヘッドノードである場合、図2に示すように、再度リソースを取得しようとし、成功はノードを頭に設定され、そうでなければ中断、先行ノードを起こされるのを待っています
割り込みの場合#
1、一般的な買収は、割り込みが発生し、割り込みビットがクリアされ、リソースへのアクセスが成功し、割り込みをトリガ
2は、後に中断した場合に中断され得ることができ、また、割り込みビットをクリアしますが、直接のスローは例外中断
#リリース
1、同期のリリースステータス
2、現在のノードの次のノード、ウェイクを取得
共有モード
#取得します
戻り値が> = 0の場合、同期状態(状態)であれば1、同期捕捉状態は、ロックが正常に直接返さ取得残留有します
図2は、キューの共有型ノード尾にノードを追加する障害は、ノードはスピン状態に入ります
図3に示すように、最初のノードのための前駆体は、ノードが再び同期状態(状態)残差を有するかどうかを判定した場合
そうである場合、現在のノードがヘッドノードに設定されている4は、現在のノードが、実行してもよいし、すべての後続ノードが目覚め
両者の差
1、排他的ロックは、同期ステータス、正常同期状態取得時に、すなわち、1つのスレッドのみであり、共有ロック同期状態> 1、値は上位層同期コンポーネントによって決定されます
図2に示すように、その直接の後続ノードのヘッドノードの解除操作が完了した後、排他ロック・キュー、共有ロックキューのヘッドノード放出は、後続のすべてのノードの実行が完了しました
同期が正常状態を取得しながら、ケース3は、共有ロックの複数のスレッド(即ち、キューノードの同期)が表示されます
15、リエントラントロックReentrantLockの
#取得します
1は、現在ロックを持っており、所有者が現在のスレッドであれば、再度、再入国を高めます
2、ロックが現在である場合、ロックモードを取得する直接的な試みが公正な待機スレッドが存在するかどうかを判断しません、非エクイティ・モードの下で資源を独占する直接の試み
16、カウンタたCountDownLatch
図1に示すように、共有モード、初期設定の固定数の設定状態を使用して
図2は、方法は、状態がゼロに達したとき、tryAcquireShared取得モードを書き換え、acquireShared方法割り込み同期を呼び出し、それはリソースが利用可能で表し待ちます
図3は、カウントダウン方式、同期releaseSharedメソッド呼び出しは、状態が保存され続け
17、読み書きをロックReentrantReadWriteLock
ロックを書きます
#取得します
1は、現在ロックフリーの状態で、排他モードで書き込みロックを取得し、
2、あなたがwriterShouldBlockを設定した場合、直接リターン偽
現在ロックされた状態の1、
2、読み取りロック、ダイレクトリターン偽があります
3、そうでない場合はfalse、現在のスレッド、再入国場合は、ロックを書きます
ロックを読みます
図1は、そこに書き込みロックであると書く場合、ロックは、現在のスレッドに戻りない-1
2、ない書き込みロックが存在しない場合、あなたはreaderShouldBlockを設定した場合、再入力して、読み取りロックを取得しようとする判決