マルチスレッド アプリケーションを開発するときは、通常、スレッドの作業を整理する必要があります。アプリケーションが大きくなり、マルチスレッドタスクに必要なスレッドが増えるほど、実行可能私たちが作るオブジェクト。

ここで、Java でのスレッドの作成はかなり高価な操作であることに注意してください。操作を実行するたびにスレッドの新しいインスタンスを作成すると、パフォーマンスに大きな問題が発生し、その結果、アプリケーションの健全性に大きな問題が発生します。

ここでスレッドプールThreadPoolExecutor が役に立ちます。

スレッドプールは、事前に初期化されたスレッドのセットです。そのサイズは固定または可変にすることができます。

スレッドよりもタスクの数が多い場合、タスクはタスク キューで待機します。プール内の N 番目のスレッドはキューからタスクを取得し、それが完了した後、スレッドはキューから新しいタスクを取得します。キュー内のすべてのタスクが実行されると、スレッドはアクティブなままになり、新しいタスクを待ちます。新しいタスクが表示されると、スレッドもそれらの実行を開始します。

スレッドプールエグゼキュータ

Java 5 以降、Executor フレームワークにはマルチスレッド ソリューションが追加されました。一般に、これには多くのコンポーネントがあり、その目的はキューとスレッド プールを効率的に管理できるようにすることです。

主なインターフェイスはExecutorExecutorServiceです。

Executor は、単一の voidexecute(Runnable runnable) メソッドを備えたインターフェイスです。

このメソッドの実装にタスクを渡すときは、将来的には非同期で実行されることを認識してください。

ExecutorService — Executorインターフェイスを拡張し、タスクを実行する機能を追加するインターフェイス。実行中のタスクを中断し、スレッド プールを終了するメソッドもあります。

ThreadPoolExecutor はExecutorインターフェイスとExecutorServiceインターフェイスを実装し、タスクの作成とタスクの実行を分離します。Runnableオブジェクトを実装し、それらをエグゼキューターに送信する必要がありますThreadPoolExecutorタスクを実行し、スレッドを作成して操作します。

タスクが実行のために送信されると、プール内の既存のスレッドが使用されます。これによりパフォーマンスが向上します。これにより、新しいスレッドの作成と初期化、そしてスレッドの作成が完了した後のガベージ コレクションでリソースを浪費するという問題が解決されます。

ThreadPoolExecutor には 4 つのコンストラクターがあります。


ThreadPoolExecutor(
int corePoolSize,
int maximumPoolSize,
long keepAliveTime, 
TimeUnit unit, 
BlockingQueue<Runnable> workQueue)
    

ThreadPoolExecutor(
int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
RejectedExecutionHandler handler)
    

ThreadPoolExecutor(
int corePoolSize,
int maximumPoolSize,
long keepAliveTime, 
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory)
    

ThreadPoolExecutor(
int corePoolSize,
int maximumPoolSize,
long keepAliveTime, 
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory, 
RejectedExecutionHandler handler)
    

ThreadPoolExecutorコンストラクターに次のパラメーターがあります。

コアプールサイズ このパラメータは、executor サービスの開始時に準備が完了している (開始されている) スレッドの数を示します。
最大プールサイズ executor サービスが作成できるスレッドの最大数。
キープアライブ時間 スレッド数が次の値より大きい場合に、解放されたスレッドが破棄されるまで存続する時間。コアプールサイズ。時間単位は次のパラメータで指定します。
ユニット 時間単位 (時間、分、秒、ミリ秒など)。
ワークキュー タスクのキューの実装。
ハンドラ 完了できないタスクのハンドラー。
スレッドファクトリー オンデマンドで新しいスレッドを作成するオブジェクト。スレッド ファクトリを使用すると、新しいスレッドの呼び出しがハードウェアに依存せず、アプリケーションが特別なスレッド サブクラス、優先順位などを使用できるようになります。

ThreadPoolExecutorの作成

Executorsユーティリティ クラスを使用すると、 ThreadPoolExecutor の作成を簡素化できます。このユーティリティ クラスのメソッドは、スレッドプールエグゼキュータ物体。

newFixedThreadPool — 任意の数のタスクを実行するために固定数のスレッドを再利用するスレッド プールを作成します。

ExecutorService executor = Executors.newFixedThreadPool(10);
                    
newWorkStealingPool — スレッド数が JVM で使用可能なプロセッサ コアの数と等しいスレッド プールを作成します。デフォルトの同時実行レベルは 1 です。これは、JVM で使用できる CPU コアと同じ数のスレッドがプール内に作成されることを意味します。同時実行レベルが 4 の場合、コア数の代わりに渡された値が使用されます。

ExecutorService executor = Executors.newWorkStealingPool(4);
                    
newSingleThreadExecutor — すべてのタスクを実行するための単一スレッドを持つプールを作成します。

ExecutorService executor = Executors.newSingleThreadExecutor();
                    
newCachedThreadPool — 必要に応じて新しいスレッドを作成するスレッド プールを作成しますが、以前に作成されたスレッドが利用可能な場合は再利用します。

ExecutorService executor = Executors.newCachedThreadPool();
                    
newScheduledThreadPool — 指定された遅延後または定期的にコマンドを実行するようにスケジュールできるスレッド プールを作成します。

ScheduledExecutorService executor = Executors.newScheduledThreadPool(10);
                    

次のレッスンでは、各タイプのプールについて検討します。