高い同時実行Javaプログラミング学習のまとめ

ここに画像を挿入説明
1、なぜ?スレッドプールを使用します
ときどき、システムは、要求の実行時間の多くを処理する必要がある各要求は、新しいスレッドを開くためにあれば、時には過ごし作成、システムは常にスレッドを作成し、破壊され、非常に短く、リアルタイムスレッドの実行よりも長いスレッドの破壊に時間。
そして時にあまりにも多くのスレッド、システムはそれを我慢できないことがあります。
:いくつかの主要な問題を解決するために、スレッドプールを使用して
スレッドプールのスレッドを再利用することにより、各スレッドの作成と破棄のパフォーマンス・オーバーヘッドを低減することができます。
このようようにスタートサイクルの実行、同時制御とのタイミングとして、いくつかの保守・管理を通します。

プール内の2、threadpoolexecutorスレッド、行うために使用されるパラメータの各?
エグゼキュータは、基本的なスレッドプールとのインターフェースは、彼と一緒に対処するため、関連するべきであるです。

エグゼキュータ・インタフェースは非常にシンプルですが、唯一の方法を実行します。

スレッドプールは、主として、これらの方法を使用した後ExecutorServiceのサブインタフェースの執行、スレッドのいくつかの一般的に使用される制御方法の増加です。

AbstractExecutorServiceは抽象クラスであり、ThreadPoolExecutorは、このクラスの実現です。

ThreadPoolExecutorパラメータ:

ThreadPoolExecutor mExecutor =て、新しいThreadPoolExecutor(corePoolSize、 // スレッドのコア数
maximumPoolSize、//スレッドの最大数
keepAliveTimeが、//アイドル・スレッド生存時間
TimeUnit.MILLISECONDS、//時間単位
新しいLinkedBlockingDeque()//スレッドキュー
Executors.defaultThreadFactory() //スレッドファクトリ
新しいAbortPolicy()//キューがいっぱいですが、スレッドの例外処理戦略以上の現在の数が最大スレッド数
);
corePoolSize:
スレッドのコア数、ケース内のデフォルトのコアのスレッドでも、アイドル状態では、生きているだろう制限を受けないkeepAliveTimeがが存在します。allowCoreThreadTimeOutがtrueに設定されていない限り。
maximumPoolSize:
スレッドプール内のスレッドの最大数を収容することができます。このスレッドの数よりも多くがブロックされます。タスクキューはLinkedBlockingDequeサイズに設定されていない場合は、この値は無効です。
keepAliveTimeが:
非中核スレッドのアイドル時間は、この時間以上が回収されます。
ユニットは、
例えばTimeUnit.SECONDSとしてkeepAliveTimeが単位を指定します。真allowCoreThreadTimeOutに設定するとcorePoolSizeに有効になります。
ワークキュー

  1. タスクキューのスレッドプール
    を使用、3つのキュー、SynchronousQueue、LinkedBlockingDeque、ArrayBlockingQueueがあります。
    threadFactory
    新しいスレッドを作成するための機能を提供するスレッドファクトリ、。ThreadFactoryインターフェイス、唯一の方法であります

ThreadFactory {パブリックインターフェイス
スレッドnewthread(RunnableをR&LT)を;
}
スレッドのスレッドファクトリの属性によってカスタマイズすることができます。工場出荷時のデフォルトは次のとおりです。

静的クラスDefaultThreadFactoryはThreadFactoryを実装{
プライベート静的最終のAtomicInteger poolNumber =新規のAtomicInteger(1)。
民間最終スレッドグループグループ;
民間最終のAtomicInteger threadNumber =新しいのAtomicInteger(1);
民間最終文字列namePrefix。

DefaultThreadFactory(){
セキュリティマネージャVAR1 = System.getSecurityManager()。
this.group = VAR1 = nullをvar1.getThreadGroup():にThread.currentThread()getThreadGroup();!?。
this.namePrefix =「プール|」+ poolNumber.getAndIncrement()+「-thread-」。
}

パブリックスレッドnewThread(RunnableをVAR1){
スレッドVAR2 =新しいスレッド(this.group、VAR1、this.namePrefix + this.threadNumber.getAndIncrement()、0L)。
IF(var2.isDaemon()){
var2.setDaemon(偽)。
}
IF(var2.getPriority()= 5!){
var2.setPriority(5)。
}
VAR2を返します。
}
}
のRejectedExecutionHandler
のRejectedExecutionHandler也是接口、只有一个一个方法

インタフェースのRejectedExecutionHandler {公共
;ボイドrejectedExecution(Runnableをvar1が、ThreadPoolExecutorをVAR2)
}
プール内のすべてのスレッドは、新しいスレッドを追加するために使用されているリソースが拒否され、コールrejectedExecutionのRejectedExecutionHandler方法。

図4は、使用して内部スレッドプールのルールについて話
素晴らしい関係のルールとタスクキューを実行するスレッドプールのスレッドを。
ここでは、タスクキューにサイズ制限を負いません:
スレッドの数が<=カーネルスレッドの数は、その後、直接ではないキューに置かれたタスクを実行するためにカーネルスレッドを起動した場合。
スレッド>コアスレッドの数が、スレッドの<=最大数、およびタスクキューの数は、タスクキューのタスクキュー上のカーネルスレッドの数よりも多くのLinkedBlockingDeque時間、ある場合。
スレッド>コアスレッドの数が、スレッドの<=最大数、およびタスクキューの数がSynchronousQueueある場合は、スレッド・プールは、ジョブキューに配置されていませんでしタスクを実行するための新しいスレッドを作成したとき。これらのスレッドは、タスクが完了した後、アイドル時間がタイムアウトがクリアされます達する、非コアスレッドです。
スレッド>コアスレッドの数、および>スレッドの最大数の数、タスクキューがあるLinkedBlockingDequeは、タスクキューキュー上のタスクのコアスレッドを超えてしまう場合。タスクキューはLinkedBlockingDequeなしサイズ制限は、スレッドプール内のスレッドの最大数を設定無効である場合には、あるスレッドの彼のコア数は、スレッドの最大数を超えません。
スレッドプールは、タスクを追加し、例外をスローすることを拒否したため、タスクキューは、SynchronousQueue時間でスレッド>スレッドのコア数、および>スレッドの最大数、数の場合。
タスクキューのサイズ制限すると
LinkedBlockingDequeが満たされ、新しいタスクが直接作成したスレッドの数が例外をスローするスレッドの最大数を超えた場合、実行する新しいスレッドを作成します。
数に制限をSynchronousQueueません。彼はこれらのタスクを続けるが、直接実行のためのスレッド・プールにはありませんので。タスクの数を超える場合には、スレッドの最大数は、直接例外をスローします。

  1. 一般的な方法のAtomicInteger
    公共最終INT getAndSet(INT newValueに) // とのAtomicIntegerに戻り、newValueがOLDVALUE添加提供
    公共のcompareAndSet最終のブール(INT、INTの更新を期待)//入力と等しくなるように設定期待値であれば、真の/偽に戻る
    パブリックファイナルint型getAndIncrement()//前の原子の1つのAtomicIntegerを追加し、現在のエネルギー自給の値を返す
    パブリック最終int型getAndDecrementを(1)のAtomicInteger原子のための減算値から戻る前に//保存
    公共int型getAndAdd決勝(デルタをint型) AtomicInteger原子と返す値//するデルタ値追加する前に
    、公共のint最終incrementAndGetを()// 1。のAtomicInteger原子に追加して加算した値を返します。1
    公共int型最終decrementAndGet()//のAtomicInteger原子のために保存値1マイナス1を返す
    //公共int型最終addAndGet(int型のデルタ)を追加した後のAtomicInteger原子プラスデルタ値と値に指定された
    6を、ThreadLocalのは、それを使用しましたか?どのように使用するには?
    JDK 1.2の初期バージョンとしてjava.lang.ThreadLocal、ThreadLocalの同時マルチスレッドプログラムの問題を解決するための新しい方法を提供しています。このツールを使用すると、美しいマルチスレッドプログラムを書くための非常に単純なクラスであることができます。
    ThreadLocalの仮定、あまりにも文字通りたくなる「スレッドローカル。」
    実際には、ThreadLocalのは、スレッドではありませんが、おそらくそれが簡単にThreadLocalVariableのいくつかを理解するために名前のローカル変数を、スレッド。
    各スレッドでのThreadLocal変数は、コピーを作成し、各スレッドは、変数の独自の内部コピーにアクセスすることができます。
    ThreadLocalのスレッドが変数ツールのローカルコピーです。スレッドとスレッドに格納されているオブジェクトのプライベートコピーは、マッピングを行うために、主のために、非常に同時シナリオでは、お互いを乱すことなく、個々のスレッド間の変数は、特に、各スレッドが意味をなさない従属変数の値のために、状態の呼び出しなしで達成することができます完全なシーン操作。

ConnectionManager {クラス
プライベート静的接続の接続= NULL;
パブリック静的接続OpenConnectionメソッド(){
(接続== NULL)IFは{
たDriverManager.getConnection =()を接続し;
}
;接続を返す
}
パブリック静的ボイドcloseConnection(){
(コネクト= IF!ヌル)
connect.close();
}
}
シングルスレッドでこのコードを使用して、データベース・リンクの管理クラスを考えてみては問題ありませんが、あなたが複数のスレッドを使用している場合ですか?もちろん、複数のスレッドを使用すると、スレッドの安全性の問題に存在します。まず、2つの方法がありますが同期されませんでした、それはプロセスに数回接続OpenConnectionメソッドを作成することができ、2番目、接続は共有変数であるので、それは可能性の高い接続データベース操作を使用してスレッドで、別のスレッドがcloseConnection近いリンクを呼び出すため必然的な必要性の代わりに、同期スレッドセーフを保護するために電話を接続します。
だから、スレッドの安全性を考慮して、このコードを同期するために、2つの方法であるとしても、同期の必要性を接続するために電話をかける必要があります。

接続データベース操作を使用している場合、スレッドは、他のスレッドが待つので、これは非常に、プログラムの実行の効率に影響を与えます。

だから我々は慎重または終了で共有するローカル変数を接続する必要があり、この問題を分析する必要がありますか?実際には、これは必須ではありません。各スレッドは、各スレッド間を接続するための接続変数、変数のアクセスは、実際には依存関係はありませんしている場合、それはスレッド他のスレッドが、これは修正された接続するかどうかを気にしません。
ここでは、友人があるかもしれません。この変数は必要ありませんので、スレッド間で共有することを考えて、直接このように処理することができ、各メソッドの特定の使用は、データベース接続を必要とし、その後、再リリースメソッドの呼び出しが完了した場合は、データベース・リンクを作成この接続。たとえば、次のよう:

クラスのConnectionManager {
プライベート接続は= NULLを接続します。
パブリック接続OpenConnectionメソッド(){
(== NULLを接続する)場合、{
()=たDriverManager.getConnectionを接続します。
}
接続返します。
}

public void closeConnection() {
    if(connect!=null)
        connect.close();
}

}

クラスダオ{
公共ボイド挿入(){
のConnectionManagerのConnectionManager =新規のConnectionManager()。
接続の接続= connectionManager.openConnection()。

    //使用connection进行操作
     
    connectionManager.closeConnection();
}

}
接続内部メソッドが作成されるたびに、スレッドの安全性の問題は、スレッド間で自然に存在しないため、この治療法は、何の問題もありませんでした。しかし、それは致命的な効果を持っているでしょう:圧力にサーバーが非常に大きくなり、そして真剣にプログラムの実行性能に影響を与えます。この方法は、真剣に、プログラムの実行の効率に影響を与えるので、無限、頻繁にデータベース接続を開閉する必要があるので、それはまた、サーバー上の巨大な圧力につながる可能性があります。

ThreadLocalの各スレッドは、変数のコピーで作成されているので、この場合でのThreadLocalの使用は、しかし右クリック、つまり、内部の各スレッドは変数を持つことになり、内部のスレッドでどこでも使用することができ、何のスレッド安全性の問題がないように独立して、スレッド間の相互の、それは真剣に、プログラムの実行性能には影響しません。

注意は、しかし、ThreadLocalのは、上記の問題を解決することができますが、しかし、理由はそれぞれのスレッドに、このような大きなThreadLocalの使用していない以上、メモリ使用量などのリソース、その消費量を考慮することのコピーを作成すると述べました。

上記のグラフから、我々はThreadLocalのコアメカニズムを垣間見るを持っている:
それぞれが内部スレッドスレッドマップを持っています。
スレッドローカルストレージオブジェクト(キー)とスレッド変数(値)のコピーを内部地図
の変数は、しかし、内部のマップは、マップの値を取得および設定を担当するスレッドによってThreadLocalの、ThreadLocalのことで維持されているスレッド。
だから、別のスレッドのために、あなたは値のコピーを取得するたびに、他のスレッドがお互いを乱すことなく、現在のスレッドの値のコピーにフォーム分離のコピーを取得することはできません。

  1. ThreadLocalのクラスには、メソッド、次のいくつかのコアを提供します:
    メソッド名機能
    の変数値の現在のスレッドのコピー取得するために使用される公開Tのget()get()メソッド
    、変数ます。public voidセット(T値)のコピーをセット () メソッドは、現在のスレッドの値を保存するために使用されます
    公共ボイドのremove()削除()メソッドは、変数の将来値の現在のコピー削除
    8、どのような違いプログラム、プロセス、現実的な例を挙げてスレッドを?
    プログラム(プログラム):命令のセットです。プログラムは、システムがそれのためにリソースを割り当て、実行するためにメモリにロードされるように、独立して実行することはできません。

プロセス(プロセス):上述したように、プロセスと呼ばれるプログラムの実装。プロセスがリソース割当システムの独立したユニットであり、各プロセスは特定のアドレススペースを占有します。プログラムは、プロセスの静的なテキスト記述で、プロセスは、システム内の動的な活動プログラムのための実行です。

スレッド(スレッド):プロセス「コントロールの単一の連続流れ」。CPUスレッドスケジューリングおよび割り当ては基本単位であるプロセスの基本的な単位はまた、軽量プロセスとして知られている、独立して実行することができるよりも小さいです。スレッドが独立して存在することはできません、それはプロセスに接続する必要があります。プロセスは、並列複数のスレッドを含むことができ、1つのスレッド確かプロセスの一部です。Java仮想マシンは、アプリケーションが複数のスレッドを同時に実行することができます。例:ワークショッププログラムがある場合は、現在進行中のタスクのワークショップの生産はプロセスであり、ワークショップに異なるジョブに従事する各ワーカースレッドです。

次のコードは、実際には、実行中の複数のスレッドがあります。

公共の静的な無効メイン(文字列[] ARGC)スロー例外{
RunnableをR =新しいThread6()。
スレッドt =新しいスレッド(R、「名前試験」)。
t.start();
}

2:スレッドTとmain()メソッド(メインスレッド)。

9、スレッドの状態
スレッドは、通常、5つの状態があり、準備ができて、ランニング、ブロッキングと死の状態を作成します。

障害物の場合は3種類に分けられます。

ブロックを待っている:()メソッドスレッドの実行待ちを実行し、すべてのリソースが占有スレッドのリリースでは、JVMは「待つプール」にスレッドします。この状態を入力した後、自動的に目を覚ますことができない、我々は他のスレッドの呼び出しは(通知に依存しなければならない)、またはウェイクアップするのnotifyAll()メソッド、クラスメソッドオブジェクトを待ちます

同期ブロック:同期ロックが別のスレッドによって占有されている場合、同期ロックオブジェクトの取得時に実行中のスレッドは、JVMにスレッドが「プールをロック」されます。

他のブロッキング:実行睡眠のスレッド()やjoin()メソッド、またはI / O要求を発行し、JVMは、スレッドがブロックされているが設定されます。睡眠()タイムアウト、参加()またはタイムアウトは、スレッドの終了を待つか、I / O処理が再びレディ状態に、スレッドを終了しました。スレッドクラスメソッド睡眠。

新しい状態(新):新しいスレッドオブジェクトを作成します。

レディ状態(Runnableを):スレッドオブジェクトを作成した後、他のスレッドは、オブジェクトのstart()メソッドを呼び出します。プール内の実行可能スレッドが配置されているスレッドの状態は、CPUを使用する権利を獲得するために待機し、実行可能となっています。

状態(ランニング)の実行:スレッドの準備状態は、CPUを取得し、プログラムコードを実行します。

ブロックされた(ブロック):スレッドがCPUを使用する権利を放棄するためにいくつかの理由でブロックされて一時的に実行を停止します。レディ状態にスレッド、ランニング行く機会まで。

死の状態(デッド):スレッドの実行が上や、異常終了するrun()メソッド、ライフサイクルの糸端です。

10は、約話をする:睡眠、収率、参加との間の差を、方法待つ
待機する時間を指定するためにスリープ()メソッドを、それが現在実行中のスレッドがブロック状態に、指定された期間内に懸架されることができ、この方法だけでなくすることができ他の優先度が同じか高い優先度のスレッドが実行するチャンスを得るが、また、低優先度のスレッドが実行する機会を得ることができます。しかし、睡眠()メソッドが同期化されている場合、シンクブロック他のスレッドがまだ共有データにアクセスすることができないことを意味し、「ロックフラグを」解放しません。スレッドに作用します

Thread.sleepを()、スレッド、CPUを入れてスレッドスケジューラの実行を中断します。

Thread.sleep()メソッドは、それが現在のスレッドの実行を中断され、静的メソッドです。

二つの方法のJavaのスリープがありますが、パラメータは1ミリ秒、および他のナノ秒のパラメータの2ミリ秒です。

waitメソッドとは異なり、睡眠方法は、ロックを解除しません

別のスレッドがスレッドが睡眠を中断した場合は、睡眠方法は、中断例外をスローします。

目覚め休止状態のスレッドがCPUを取得することを保証することはできませんした後、それは最初に他のスレッドのCPUと競合し、準備完了状態になります。

エラーの発生しやすい場所は、スレッドがトンを一時停止するときに()t.sleepを呼び出すとき、あります。これはのThread.sleepが静的メソッドであるため、それは代わりに、スレッドの現在のスレッドがトンスリープ状態になります、間違っています。

参加する():現在のスレッドを待機さ、このメソッドを呼び出したスレッドは、先に進む前に終了します。例えば:、Tスレッド実行が完了しているような、メインメソッドは、この時点でブロックされた状態を入力すること、メインメソッドt.join()を呼び出すmainメソッドと続行する準備ができて、準備完了状態に戻ります。

意味のある方法に参加するスレッドのstartメソッドが呼び出された後に呼び出さなければなりません。また、これは理解することは非常に簡単です:スレッドが起動しなかった場合、それは同期されませんことを。スレッドに作用します

11、のnotifyAllメソッドが行うThreadクラスで定義され、通知、待つのか?どのような役割をしていますか?
待って()、()に通知し、のnotifyAll() 各オブジェクトが待機()、通知()、持っていることを意味し、Threadクラスに属しているが、Objectクラスに属していないのnotifyAll() 関数を。

各オブジェクトはロックが各画像に基づいているので、ロックを有し、(待機)、()を通知する、のnotifyAll()は、ロック方式に関連しています。

3つの方法の効果は以下のとおりです。

待つ:別のスレッドがオブジェクトの通知()メソッドまたはのnotifyAll()メソッドを呼び出すまで、現在のスレッドがブロックを入力するように待機します。
現在のスレッドがこのオブジェクトのモニター(オブジェクトロック)を所有している必要があります。呼び出すことにより、別のスレッドになるまで、このモニタと待ちのスレッドを解放所有権

方法に通知、またはこのモニタオブジェクトのメソッドのnotifyAll通知スレッドは、ウェイクアップを待ちます。スレッドが継続してモニターの所有権を取り戻すために、それまで待ちます。

通知:ウェイクアップこのオブジェクト上の単一スレッド・モニター(オブジェクト・ロック)を待機します。すべてのスレッドがこのオブジェクトで待機している場合は一つのスレッドを覚ます選択されます。このオブジェクトのロックまで、現在のスレッドが起こされるためにスレッドを続行するには、放棄するため。このメソッドは、呼び出すために、このオブジェクトの監視スレッドの所有者として使用する必要があります。「現在のスレッドがこのオブジェクトのモニターを所有しなければならない」と「この方法が唯一の所有者を呼び出すために、このオブジェクトのモニターのスレッドとして使用されるべきで、」待ち時間を説明しましたこの方法は、(OBJ内)、すなわち同期、シンクブロック内で実行されなければならない方法と通知します。

notifyAll:このオブジェクトのモニター(オブジェクトロック)上のウェイクアップすべてのスレッドが待機します。
清聴ありがとうございました!詳しくはプラスqq1723082823については

おすすめ

転載: blog.csdn.net/yxxylucy/article/details/92700393