Executor、ExecutorService、Executorsの違い(転送)

元のソース:http//www.importnew.com/24923.html

java.util.concurrent.Executor、java.util.concurrent.ExecutorService、java.util.concurrent。Executorsこれら3つはすべてJava Executorフレームワークの一部であり、スレッドプール機能を提供するために使用されます。スレッドの作成と管理は非常に面倒であり、オペレーティングシステムは通常スレッドの数を制限するため、要求が来るたびにスレッドを作成するのではなく、スレッドプールを使用してタスクを同時に実行することをお勧めします。スレッドプールを使用すると、アプリケーションの応答時間を改善できるだけでなく、「java.lang.OutOfMemoryError:新しいネイティブスレッドを作成できません」などのエラーを回避できます。

Java 1.5では、開発者はスレッドプールの作成と管理に注意を払う必要がありますが、Java 1.5以降、Executorフレームワークは、FixedThreadPool(固定数のスレッドを含む)、CachedThreadPool(必要に応じて新しいスレッドを作成できます)など、さまざまな組み込みスレッドプールを提供します。スレッド)など。

エグゼキュータ

Executor、ExecutorService、およびExecutorsの主な違いは、Executorが抽象コアインターフェイスであるということです(おおよそのコードは次のとおりです)。

public interface Executor {
    void execute(Runnable command);
}

タスクと実行を結合するjava.lang.Threadクラスとは異なり、Executorはタスク自体を実行タスクから分離します。ThreadとExecutorの違いについては、ThreadとExecutorの違いを参照してください。

ExecutorService

ExecutorServiceインターフェイスは、Executorインターフェイスを拡張し、Futureオブジェクトを返し、スレッドプールを終了し、閉じるためのメソッドを提供します。shutdownメソッドが呼び出されると、スレッドプールは新しいタスクの受け入れを停止しますが、保留中のタスクは完了します。

Futureオブジェクトは非同期実行を提供します。つまり、タスクの実行が完了するのを待つ必要はありません。実行する必要のあるタスクを送信し、必要に応じてFutureに結果があるかどうかを確認するだけです。タスクが実行されている場合は、Future.get()を使用できます。メソッドは実行結果を取得します。Future.get()メソッドはブロッキングメソッドであることに注意してください。タスクが呼び出されたときにタスクが完了していない場合、タスクの実行が終了するまで待機します。

タスクの実行は、ExecutorService.submit()メソッドによって返されるFutureオブジェクトを介してキャンセルすることもできます。Futureは、保留中のタスクの実行をキャンセルするcancel()メソッドを提供します。

ExecutorServiceのコードの一部は次のとおりです。

public interface ExecutorService extends Executor {
    void shutdown();
    <T> Future<T> submit(Callable<T> task);
    <T> Future<T> submit(Runnable task, T result);
    <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) throws InterruptedException;
}

遺言執行者

Executorsは、Collectionsに似たツールクラスです。FixedThreadPoolやCachedThreadPoolなど、さまざまなタイプのスレッドプールを作成するためのファクトリメソッドを提供します。

コードの実行者の部分:

public class Executors {
    public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>());
        }
         
     public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>());
        }
}

3つの違いを詳しく見てみましょう。

Executor vs ExecutorService vs Executors

上記のように、これら3つはすべてExecutorフレームワークの一部です。Javaが提供するさまざまなタイプのスレッドプールをより効率的に使用するには、Java開発者がそれらを学習して理解する必要があります。誰もがよりよく理解できるように、これら3つの違いを要約してください。

  • ExecutorインターフェイスとExecutorServiceインターフェイスの主な違いは、ExecutorServiceインターフェイスがExecutorインターフェイスを継承し、Executorのサブインターフェイスであることです。
  • ExecutorとExecutorServiceの2つ目の違いは、ExecutorインターフェイスがRunnableインターフェイスオブジェクトを受信するexecute()メソッドを定義するのに対し、ExecutorServiceインターフェイスのsubmit()メソッドはRunnableおよびCallableインターフェイスオブジェクトを受け入れることができることです。
  • ExecutorインターフェイスとExecutorServiceインターフェイスの3番目の違いは、Executorのexecute()メソッドは結果を返さないのに対し、ExecutorServiceのsubmit()メソッドはFutureオブジェクトを介して操作の結果を返すことができることです。
  • ExecutorインターフェイスとExecutorServiceインターフェイスの4番目の違いは、クライアントがタスクを送信できるようにすることに加えて、ExecutorServiceはスレッドプールを制御するメソッドも提供することです。例:shutDown()メソッドを呼び出して、スレッドプールを終了します。スレッドプールを閉じる方法と保留中のタスクを処理する方法について詳しくは、Java ConcurrencyinPractice」を参照してください。
  • Executorsクラスは、さまざまなタイプのスレッドプールを作成するためのファクトリメソッドを提供します。例:newSingleThreadExecutor()は1つのスレッドのみでスレッドプールを作成し、newFixedThreadPool(int numOfThreads)は固定数のスレッドでスレッドプールを作成し、newCachedThreadPool()は必要に応じて新しいスレッドを作成できますが、既存のスレッドがアイドル状態の場合、それらは再利用されます。スレッドがあります。

総括する

次の表に、ExecutorとExecutorServiceの違いを示します。

翻訳者のメモ

個人的には、Executorsクラスが提供するfactoryメソッドを使用してスレッドプールを作成するのは非常に便利だと思いますが、実際の状況に応じてスレッドプールの一部のパラメーターをカスタマイズする必要があるシナリオには適していません。

例:
スレッドプール内のスレッドが動作状態にあり、スレッド数がスレッドプールで許可されている最大スレッド数に達した場合、指定された飽和戦略が採用されて、新しく送信されたタスクが処理されます。合計で4つの戦略があります。

  • AbortPolicy:例外を直接スローします
  • CallerRunsPolicy:呼び出し元のスレッドを使用してタスクを実行します
  • DiscardOldestPolicy:スレッドキュー内の最新のタスクを破棄し、新しく送信されたタスクを実行します
  • DiscardPolicyは新しいタスクを直接破棄します

Executorsのfactoryメソッドによって作成されたスレッドプールを使用する場合、飽和戦略はデフォルトのAbortPolicyであるため、スレッドプールがいっぱいになったときに呼び出し元のスレッドを使用してタスクを実行する場合は、自分でスレッドプールを作成し、指定する必要があります。エグゼキュータを使用する代わりに、飽和戦略が必要です。

したがって、必要に応じてThreadPoolExecutor(ExecutorServiceインターフェイスの実装クラス)オブジェクトを作成し、Executorsのfactoryメソッドを呼び出す代わりにいくつかのパラメーターをカスタマイズできます。

もちろん、Springフレームワークを使用するプロジェクトでは、Springが提供するThreadPoolTask​​Executorクラスを使用してスレッドプールを作成することもできます。ThreadPoolExecutorと同様に、ThreadPoolTask​​Executorは、コアスレッドプールサイズ、スレッドプールの最大数、飽和戦略、スレッドアクティビティの保持時間など、スレッドプールをカスタマイズするための多くのパラメーターも提供します。

おすすめ

転載: blog.csdn.net/u013821237/article/details/89553610