スレッドの道を作成します。
- 継承スレッド
- 実行可能な実装
- スレッドプール
- FurureTask /呼び出し可能
最初:継承スレッド
DEMO1:
パブリック クラスDEMO1 { 公共 静的 ボイドメイン(文字列[]引数){ 新しいMyThread()(開始)。 } } クラス MyThreadは延びスレッド{ 公共 ボイドラン(){ System.out.printlnは( "线程创建" )。 } }
第二:実行可能な達成するために、
DEMO2:
パブリック クラスDEMO2 { 公共 静的 ボイドメイン(文字列[]引数){ 新しいスレッド(新しいMyThreadRun())(開始)。 } } クラス MyThreadRun 実装Runnableを{ @Override 公共 ボイドラン(){ System.out.printlnは( "线程创建" )。 } }
実行可能なインターフェイスの実装を使用する場合は、我々は一般的に匿名クラスの形式を使用します。
パブリック クラスDEMO2 { 公共 静的 ボイドメイン(文字列[]引数){ 新しいスレッド(新しいRunnableを(){ @Override 公共 ボイドラン(){ System.out.printlnは( "线程创建" ); } })。)(開始; } }
Runnableを関数インタフェースがあるので、あなたが書き込みにラムダ式を使用することができます。
パブリック クラスDEMO2 { 公共 静的 ボイドメイン(文字列[]引数){ 新しいスレッド(() - > { するSystem.out.println( "线程创建" ); })。(開始) } }
第三:スレッドプールを使用しました:
まず、スレッドプールの利点を見て:
スレッド数を超えた場合にタスクがキュー・プロセスに配置されます、実行中のスレッドの長い制御など数として仕事をして、スレッドの作成後にこれらのタスクを開始するスレッドプールは、最大数は数を超えますスレッドラインで待っていると、他のスレッドが終了し、タスクを実行するためにキューから削除します。
その主な機能は次のとおりです:スレッドの多重化、同時制御の最大数、スレッドを管理します。
まず:リソースの消費を削減します。スレッドを再利用することにより、ピンの消費によって引き起こされるスレッドの作成と破壊を軽減するために作成されています。
第二:応答速度を向上させることができます。ミッションが到着すると、タスクがすぐに実装することができ、スレッドの作成を待つ必要がないかもしれません。
第三に:スレッドの管理性を向上させるために。無制限の作成は、リソースの浪費を販売するだけでなく、統一された分布、チューニングおよび監視することができ、スレッドプールを使用して、システムの安定性を減らす場合、スレッドは、希少資源です。
プール内のJavaスレッドがキュータフレームワークによって実現され、我々は枠組みの中で執行、エグゼキュータ、ExecutorServiceの、ThreadPoolExecutorこれらのクラスを使用していました。
キュータスレッドプールを作成するための3つの方法があります。
// スレッドプールは、スレッドの固定数作成する ExecutorServiceのexecutorService1 = Executors.newFixedThreadPool(5 ); // スレッドプールスレッドが作成する ExecutorServiceのexecutorService12 = Executors.newSingleThreadExecutor()を; // スレッドプールスレッドが膨張作成する ExecutorServiceのexecutorService13 =エグゼキュータを。 newCachedThreadPool();
そのソースコードを見てみましょう:
パブリック 静的 ExecutorServiceのnewFixedThreadPool(int型にnthreads){ リターン 新しいThreadPoolExecutor(nthreadsの値、nthreadsの値、 0L 、TimeUnit.MILLISECONDS、 新しい LinkedBlockingQueue <Runnableを> ()); } パブリック 静的ExecutorServiceのnewSingleThreadExecutor(){ リターン 新しいFinalizableDelegatedExecutorService (新しい ThreadPoolExecutor(1、1 、 0L 、TimeUnit.MILLISECONDS、 新しい LinkedBlockingQueue <Runnableを> ())); } パブリック 静的ExecutorServiceのnewCachedThreadPool(){ 戻り 、新しい ThreadPoolExecutorを(0 、Integer.MAX_VALUEで、 60L 、TimeUnit.SECONDS、 新しい SynchronousQueue <Runnableを> ()); }
あなたは、彼らが最終的に同じメソッドを呼び出していることがわかります新新)ThreadPoolExecutor(私たちは、このコンストラクタを見てみましょう:
公共 ThreadPoolExecutor(INT corePoolSize、 INT maximumPoolSize、 長いkeepAliveTimeが、 TimeUnitでユニット、 BlockingQueueの <Runnableを> ワークキュー){ この(corePoolSize、maximumPoolSize、keepAliveTimeが、ユニット、ワークキュー、 Executors.defaultThreadFactory()、たDefaultHandler)。 }
あなたは7つのパラメータを渡すためのスレッドプールの必要性を作成するために見ることができます:
1 corePoolSize、:スレッドプール内のスレッドの永久コア番号
2、maximumPoolSize:スレッドプールは、実行スレッドの最大数を収容することができ、この値がより大きいか等しくなければならない1。
3、keepAliveTimeが:余分現在のスレッドプールアイドル・スレッド生存時間量は、アイドル時間がkeepAliveTimeがに到達corePoolSizeを超えると、過剰なスレッドは、これまでcorePoolSizeスレッドまで破壊される
ユニット、4:keepAliveTimeがユニットの
タスクキューのタスクが送信さが、まだ実行されなかった:5、ワークキュー
6、threadFactory :スレッドを作成するために使用されるスレッドプールスレッド工場でワーカースレッドの表現の生成は、一般デフォルト
のキューが一杯になったときの戦略を拒絶を示し、それらのスレッドの最大数を超えるワーカースレッドは、スレッドプール(maximumPoolSize)に等しい:7、ハンドラ戦略の実行可能な実行の要求を拒否する方法
その後、我々はここでは、スレッドプール、これらの意味の入ってくるパラメータを作成するために、これらの三つの方法で戻って見てみましょう、私たちは見ているキューをブロックBlockingQueueのキューをブロックし、拡張可能なスレッドプールを作成するときに、他の2つが使用されていません同じ。
BlockingQueueの:
ArrayBlockingQueue:ブロッキングキュー囲まれた構造体の配列。
LinkedBlockingQueue:有界からなるリスト構造(デフォルトはサイズが、Integer.MAX_VALUEである)キューを遮断。
PriorityBlockingQueue:無制限のブロッキングキューのサポートの優先順位付け。
DelayQueue:使用してキューをブロックする、無制限の優先度キューの実装を延期しました。
SynchronousQueue:ブロッキングキュー・エレメントは、すなわち、単一要素キューに格納されていません。
LinkedTransferQueue:無制限ブロッキングキューからなるリスト。
LinkedBlockingDeque:双方向のブロッキングキューで構成されるリスト。
一般的な方法:
ハンドラ:拒否する方針は、待ち行列が既にいっぱいである、決して同時に新しいタスクを合わないだろう、プール内の最大スレッドが到達し、新しいタスクは、我々は政策を拒否する必要があり、この時間を提供し続けることができません。
AbortPolicy(デフォルト):直接RejectedExecutionExceptionは、通常の予防例外スロー
CallerRunsPolicyを:、ポリシーはどちらも、それは例外をスローしません、仕事を放棄しないだろう調整機構「を、発信者が実行している」が、特定のタスクにフォールバックします呼び出し側は、新たなタスクの流れを減少させます。
DiscardOldestPolicyは:最長のタスク、現在のタスクを待っているキューを放棄してから再度試して、現在のジョブを送信するためにキューに参加します。
DiscardPolicy:このポリシーは、黙って破棄されたタスクを処理することができない、何の治療が例外をスローしません。タスクが欠落している許可した場合、これが最善の戦略です。
これらのパラメータの理解後に、我々は、スレッドプールを作成するには、3つの方法の長所と短所を知っているが、我々は、一般的に代わりにカスタム・スレッド・プールを使用するのではなく、彼らと一緒に行っていません。
ExecutorServiceのExecutorServiceの= 新しいThreadPoolExecutor( 2 、 5 、 20 、 TimeUnit.SECONDS、 新しい LinkedBlockingDeque <>(3 )、 新しい ThreadPoolExecutor.CallerRunsPolicy())。
私たちはデモを書きました:
パブリック クラスThreadPoolDemo { 公共 静的 ボイドメイン(文字列[]引数){ / * //スレッドプール内のスレッドの固定数の作成 = ExecutorServiceのexecutorService1 Executors.newFixedThreadPoolを(5); //スレッドプールスレッドを作成 ExecutorServiceのexecutorService12 = Executors.newSingleThreadExecutor (); //スレッドプールスレッド膨張作成 ExecutorServiceのexecutorService13 = Executors.newCachedThreadPool(); / * ExecutorServiceのExecutorServiceの = 新しい新しいThreadPoolExecutor( 2 、 5 、 20 、 TimeUnit.SECONDS、 新しい LinkedBlockingDeque <>(3 )、 新しいThreadPoolExecutor.CallerRunsPolicy()); 以下のために(INT I = 1; I <10; I ++ ){ 新しいスレッド(() - > { executorService.execute(() - > { 。のSystem.out.println(にThread.currentThread()のgetName() + "处理任务" ); }); }、 "" + I).start(); } } }
原理スレッドプール
1.あなたがスレッドプールを作成した後、要求を待って開始します。
:タスク要求を追加するために、execute()メソッドを呼び出すとき、次のように2、スレッドプールは、判断を行います
。2.1を実行しているスレッドの数が少なくcorePoolSizeよりも、その後すぐにこのタスクを実行するためのスレッドを作成する場合
2.2スレッドの実行数が以上である場合corePoolSize、キューで次の作業、
キューがフルタイムとランニングも少ないmaximumPoolSizeよりもスレッド2.3の数されている場合でも、すぐにこのタスクを実行するための非コアスレッドを作成する必要があり、
スレッド2.4の数をキューが満杯と実行されている場合maximumPoolSizeに等しいより以上は、そのポリシーを拒否飽和を実行するスレッドプールを開始します。
スレッドがタスクを完了する場合には、図3に示すように、それは、タスクが実行されるキューから削除されます。
スレッドは何もより一定期間(keepAliveTimeが)以下である場合4は、スレッドが決定されます:
現在実行中のスレッドの数がcorePoolSize以上である場合には、スレッドが停止されます。
スレッドプールのすべてのタスクが完了した後だから、それは最終的にcorePoolSizeのサイズに縮小します。
第四:FurureTask /呼び出し可能
使用したいFurureTask /呼び出し可能とRunnableを、のデモを見てみましょう:
クラス CallAbleTest 実装呼び出し可能{ @Override パブリック 整数 コール()はスロー例外 { リターン 1024 。 } } パブリック クラスCallableDemo { 公共 静的 ボイドメイン(文字列[]引数)がスローExecutionException、InterruptedExceptionあるが{ CallAbleTest callAbleTest = 新しいCallAbleTest()。 FutureTask <整数> futureTask = 新しい FutureTask <> (callAbleTest)。 新しいスレッド(futureTask).start(); 整数結果 = futureTask.get()。 System.out.println( + "reault" 結果)。 新しいスレッド(futureTask).start(); System.out.println( "結果:" + futureTask.get()); } }
私たちは、実装呼び出し可能インターフェース、その実装クラスを作成し、そのメソッドをオーバーライドします。私たちは、差のRunnableを見ることができます:
(1)の戻り値があるかどうか
(2)がスローされている
(3)書き換え方法は、RUNは、コールが同じではありません
FurureTask /呼び出し可能では私たちのために、より強力な方法を提供します。
呼び出し可能インターフェースの関数であるので、私たちは、匿名の内部クラスの形で書かれたラムダ式としてのRunnableのようにすることができます。
パブリック クラスCallableDemo { 公共 静的 ボイドメイン(文字列[]引数)がスローExecutionException、InterruptedExceptionある{ FutureTask <整数> futureTask = 新しい FutureTask <整数>(() - > { リターン 1024 ; }); 新しいスレッド(futureTask).start(); System.out.println( "結果:" + futureTask.get()); } }
すべてのスレッドのタスクは、ここで待つようにブロックされます、まだ完了していない場合には、ブロックする方法である、)futureTask.get(を介して取得するため、戻り値の必要性を得るために、ことに留意すべきです。たとえば、3つのスレッドのタスクがあります、
タスクを実行する5秒、3秒、2秒、その後、メインスレッドは、すべてのスレッドがタスクの終了を実行するのを待ち、5秒間ブロックします。
なぜもう一つのポイントは、新たな新しいスレッド(FutureTask、).start()は、渡すことができますFutureTaskを、私たちは見ることができ、新たな新しいスレッド()メソッド、
唯一の方法のRunnableに関連し、そしてその後、私たちは推測することができるはずであるべきfutureTaskをRunnableを実装クラスを、我々は彼らの関係の構造を見て、我々は確かにFutureTask実装クラスを見ることができます。
^ - これらは、スレッドを作成するための4つの方法は、エラーがある、^私を修正してください。