Androidのスレッドプール-[Android_YangKe]
9381 ワード
スレッドプールといえば、まずスレッドプールのメリットを話さなければなりません.読者が知っていると信じています.スレッドプールのメリットは以下の3つにまとめることができます.スレッドプール内のスレッドを再利用し、スレッドの作成と破棄によるパフォーマンスオーバーヘッドを回避します. は、スレッドプールの最大同時数を効果的に制御し、大量のスレッド間でシステムリソースを奪い合うことによるブロック現象を回避することができる. は、スレッドを簡単に管理し、タイミング実行や指定間隔ループ実行などの機能を提供することができる.
Androidのスレッドプールの概念はJavaのExecutorに由来し、Executorはインタフェースであり、真のスレッドプールの実現は
ThreadPoolExecutor
CorePoolSizeスレッドプールのコアスレッド数です.デフォルトでは、コアスレッドはアイドル状態であってもオンラインスレッドプールで生存します.
maximumPoolSizeスレッドプールに収容できる最大スレッド数は、アクティブなスレッドがこの数値に達すると、後続の新しいタスクがブロックされます.
keepAliveTime非コアスレッドアイドル時のタイムアウト時間が長く、それを超えると非コアスレッドが回収され、
unitは、
WorkQueueスレッドプール内のタスクキューでは、スレッドプールのexecuteメソッドでコミットされたRunnableオブジェクトがこのパラメータに格納されます.
threadFactoryスレッドファクトリは、スレッドプールに新しいスレッドを作成する機能を提供します.
これらの主要パラメータに加えて、スレッドプールのスレッド数がコアスレッドプールの数に達していない場合、タスクを実行するためにコアスレッドが直接起動します. スレッドプール内のスレッドの数がコアスレッドの数に達しているか、またはそれを超えている場合、タスクはタスクキューに挿入されてキュー実行されます. ステップ2でタスクをタスクキューに挿入できない場合は、タスクキューがいっぱいになっているため、スレッド数がスレッドプールで指定された最大値に達していない場合、すぐに非コアスレッドが起動してタスクを実行します. ステップ3でスレッド数がスレッドプールによって規定された最大値に達した場合、このタスクの実行は拒否され、
上記のコードから分かるように、コアスレッド数はCPUコア数+1に等しい. スレッドプールの最大スレッド数CPUコア数の2倍+1; コアスレッドにはタイムアウトメカニズムがなく、非コアスレッドのアイドル時のタイムアウト時間は1秒である. タスクキューの容量は128です.
スレッドプールの分類
上記では、
FixedThreadPool
CachedThreadPool
Executorの
スレッドプール内のスレッドがアクティブな場合、スレッドプールは新しいスレッドを作成して新しいタスクを処理します.そうしないと、空きスレッドを使用して新しいタスクを処理します.スレッドプール内の空きスレッドにはタイムアウトメカニズムがあり、このタイムアウト時間は60秒で、60秒を超えるとアイドルスレッドが回収されます.
スレッドプール全体がアイドル状態にある場合、スレッドプール内のスレッドはタイムアウトして停止されます.この場合、
ScheduledThreadPool
Executorsの
SingleThreadExecutor
Executorsの
Androidでよく見られる4種類のスレッドプールについて詳しく説明したが、上記システムが提供する4種類のスレッドプールのほか、実際のニーズに応じてスレッドプールを柔軟に構成することもできる.次のコードは,システムプリフォームの4つのスレッドプールの使用方法を示す.
注:Androidからアートを開発しました~
助けがあれば、ダブルクリック、コメント、転送、あなたの小さな手を動かしてもっと多くの人に知ってもらうのが好きです!Androidに注目YangKe
Androidのスレッドプールの概念はJavaのExecutorに由来し、Executorはインタフェースであり、真のスレッドプールの実現は
ThreadPoolExecutor
である.ThreadPoolExecutor
は一連のパラメータを提供してスレッドプールを配置し、異なるパラメータによって異なるスレッドプールを作成することができ、スレッドプールの機能特性から言えばAndroidのスレッドプールは主に4種類に分けられ、この4種類のスレッドプールはExecutorが提供した工場方法で得ることができ、具体的にはThreadPoolExecutor
で詳しく紹介する.Androidのスレッドプールは、ThreadPoolExecutor
を直接または間接的に構成することによって実現されるため、それらを紹介する前にThreadPoolExecutor
を紹介する必要があります.ThreadPoolExecutor
ThreadPoolExecutor
はスレッドプールの真の実装であり、その構造方法は一連のパラメータを提供してスレッドプールを構成し、以下にThreadPoolExecutor
の構造方法における各パラメータの意味を紹介し、これらのパラメータはスレッドプールの機能特性に直接影響し、以下はThreadPoolExecutor
の比較的一般的な構造方法である.public ThreadPoolExecutor (int corePoolSize,
long maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue workQueue,
ThreadFactory threadFactory)
CorePoolSizeスレッドプールのコアスレッド数です.デフォルトでは、コアスレッドはアイドル状態であってもオンラインスレッドプールで生存します.
ThreadPoolExecutor
のallowCoreThreadTimeOut
プロパティがtrueに設定されている場合、アイドルコアスレッドは、新しいタスクが来るのを待つときにタイムアウトポリシーがあります.この間隔はkeepAliveTime
で指定され、待ち時間がkeepAliveTime
で指定された時間を超えると、コアスレッド数は終了します.maximumPoolSizeスレッドプールに収容できる最大スレッド数は、アクティブなスレッドがこの数値に達すると、後続の新しいタスクがブロックされます.
keepAliveTime非コアスレッドアイドル時のタイムアウト時間が長く、それを超えると非コアスレッドが回収され、
ThreadPoolExecutor
のallowCoreThreadTimeOut
属性がtrueに設定されている場合、keepAliveTIme
もコアスレッドに作用する.unitは、
keepAliveTime
パラメータの時間単位を指定するために使用され、これは列挙であり、TimeUnit.MILLISECONDS
(ミリ秒)、TimeUnit.SECONDS
(秒)、TimeUnit.MINUTES
(分)などが一般的である.WorkQueueスレッドプール内のタスクキューでは、スレッドプールのexecuteメソッドでコミットされたRunnableオブジェクトがこのパラメータに格納されます.
threadFactoryスレッドファクトリは、スレッドプールに新しいスレッドを作成する機能を提供します.
ThreadFactory
はインタフェースであり、Thread newThread(Runnable r)という方法しかありません.これらの主要パラメータに加えて、
ThreadPoolExecutor
には一般的でないパラメータRejectedExecutionHandler handler
がある.スレッドプールが新しいタスクを実行できない場合、これは、タスクキューがいっぱいになっているか、タスクが正常に実行できないためかもしれません.この場合、ThreadPoolExecutor
はhandlerのrejectedExecution
メソッドを呼び出して呼び出し、デフォルトではrejectedExecution
メソッドがRejectedExecutionException
を直接投げ出します.ThreadPoolExecutor
は、RejectedExecutionHandler
にいくつかのオプション値を提供します.CallerRunsPolicy、AbortPolicy、DiscardPolicy DiscardOldesPolicy
はデフォルト値であり、AbortPolicy
は直接RejectedExecutionException
を放出します.handlerというパラメータは一般的ではないので、ここでは詳しく説明しません.ThreadPoolExecutor
タスクを実行するときは、次のルールに従います.ThreadPoolExecutor
は、RejectedExecutionHandler
のrejectedException
メソッドを呼び出して呼び出し、呼び出し元に通知する.ThreadPoolExecutor
のパラメータ構成はAsyncTaskで明らかになっています.以下はAsyncTask
のスレッドプールの構成です.private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
private static final int CORE_POOL_SIZE = CPU_COUNT + 1;
private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
private static final int KEEP_ALIVE = 1;
private static final ThreadFactory sThreadFactory = new ThreadFactory () {
private static final int AtomicInteger mCount = new AtomicInteger (1);
public Thread newThread (Runnable r) {
return new Thread (r, "AsyncTask #" + mCount.getAndIncrement ());
}
private static final BlockingQueue sPoolWorkQueue = new LinkedBlockingQueue (128);
/**
* An {@link Executor} that can be used to execute tasks in paralleb.
*/
public static final Executor THREAD_POOL_EXECUTOR = new ThreadPoolExecutor (CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);
} ;
上記のコードから分かるように、
AsyncTask
はTHREAD_POOL_EXECUTOR
というスレッドプールを配置し、配置後のスレッドプールの規格は以下の通りである.スレッドプールの分類
上記では、
ThreadPoolExecutor
の構成について詳しく説明しましたが、このセクションでは、Androidで最も一般的な4つの異なる機能特性を有するスレッドプールについて説明します.これらの4つのスレッドプールは、それぞれThreadPoolExecutor
であるFixedThreadPool、CachedThreadPool、ScheduleThreadPool SingleThreadPool
を直接または間接的に構成することによって独自の機能特性を実現します.FixedThreadPool
Executors
のnewFixedThreadPool
メソッドによって作成されます.スレッド数が固定されたスレッドプールであり、スレッドプールが閉じられない限り、スレッドプールがアイドル状態にある場合、スレッドプールは回収されません.すべてのスレッドがアクティブな場合、新しいタスクは新しいスレッドが空になるまで待機します.FixedThreadPool
はコアスレッドのみであり、これらのコアスレッドは回収されないため、外部の要求により迅速に応答できることを意味する.newFixedThreadPool
方法の実装は、FixedThreadPool
の中にコアスレッドのみが存在し、これらのコアスレッドにはタイムアウト制限がなく、またタスクキューにもサイズ制限がないことを発見することができる.public static ExecutorService newFixedThreadPool (int nThreads) {
return new ThreadPoolExecutor (nThreads, nThreads,
0L, TimeUnit.MILLISENONDS,
new LinkedBlockingQueue());
}
CachedThreadPool
Executorの
newCachedThreadPool
メソッドで作成します.非コアスレッドのみであり、最大スレッド数はInteger.MAX_VALUE
です.Integer.MAX_VALUE
は大きな数であるため、実際には最大スレッド数に相当して任意に大きくすることができる.スレッドプール内のスレッドがアクティブな場合、スレッドプールは新しいスレッドを作成して新しいタスクを処理します.そうしないと、空きスレッドを使用して新しいタスクを処理します.スレッドプール内の空きスレッドにはタイムアウトメカニズムがあり、このタイムアウト時間は60秒で、60秒を超えるとアイドルスレッドが回収されます.
FixedThreadPool
とは異なり、CachedThreadPool
のタスクキューは実際には空のセットに相当し、このようなシナリオではSynchronousQueue
はタスクを挿入できないため、任意のタスクが直ちに実行される.SynchronousQueue
は非常に特殊なキューであり、多くの場合、要素を格納できないキューを簡単にすることができます.実際には使用されていないため、ここでは深く検討しません.スレッドプール全体がアイドル状態にある場合、スレッドプール内のスレッドはタイムアウトして停止されます.この場合、
CachedThreadPool
には実際にはスレッドはなく、ほとんどシステムリソースを占有しません.newCacheThreadPool
の方法の実装を以下に示す.public static ExecutorService newCachedThreadPool () {
return new ThreadPoolExecutor (0,
Integer.MAX_VALUE, 60L,
TimeUnit.SECONDS,
new SynchronousQueue());
}
ScheduledThreadPool
Executorsの
newScheduledThreadPool
メソッドによって作成されます.コアスレッドの数は固定されており、コアスレッドの数ではなく制限されず、非コアスレッドがアイドル状態にある場合にすぐに回収されます.ScheduledThreadPool
のようなスレッドプールは、主にタイミングタスクと周期的な繰返しタスクを実行するために使用され、newScheduledThreadPool
の方法の実装は以下に示す.public static ScheduledExecutorService newScheduledThreadPool (int corePoolSize) {
return new ScheduledThreadPoolExecutor (corePoolSize);
}
public ScheduledThreadPooExecutor (int corePoolSize) {
super (corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS, new DelayedWorkQueue());
}
SingleThreadExecutor
Executorsの
newSingleThreadPoolExecutor
メソッドによって作成されます.このようなスレッドプールの内部には、すべてのタスクが同じスレッドで順次実行されることを保証するコアスレッドが1つしかありません.SingleThreadPoolExecutor
は、すべての外部タスクを1つのスレッドに統一することを意味し、これらのタスク間でスレッド同期の問題を処理する必要がない.newSingleThreadExecutor
の方法の実装を以下に示す.public static ExecutorService newSingleThreadExecutor () {
return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor (
1,
1,
0L,
TimeUnit.MILLISECONDS,
new LinkedBlockingQueue());
}
Androidでよく見られる4種類のスレッドプールについて詳しく説明したが、上記システムが提供する4種類のスレッドプールのほか、実際のニーズに応じてスレッドプールを柔軟に構成することもできる.次のコードは,システムプリフォームの4つのスレッドプールの使用方法を示す.
Runnable command = new Runnable (){
@Override
public void run (){
SystemClock.sleep(2000);
}
};
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(4);
fixedThreadPool.execute(command);
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
cachedThreadPool.execute(command);
ScheduledExecutorService scheduleThreadPool = Executors.newScheduledThreadPool(4);
//2000ms command
scheduleThreadPool.schedule(command, 2000, TimeUnit.MILLISECONDS);
// 10ms , 1000ms command
scheduleThreadPool.scheduleAtFixedRate(command, 10, 1000, TimeUnit.MILLISECONDS);
ExecutorService singleThreadPool = Executors.newSingleThreadExecutor();
singleThreadExecutor.execute(command);
注:Androidからアートを開発しました~
助けがあれば、ダブルクリック、コメント、転送、あなたの小さな手を動かしてもっと多くの人に知ってもらうのが好きです!Androidに注目YangKe