同時プログラミングのExecutorフレームワーク


Executorフレームワーク、Executors、ExecutorServiceおよびCompletionService Executor:java.util.concurrentは、Executorの一部として柔軟なスレッドプール実装を提供します.Executorは簡単なインタフェースですが、さまざまなタイプのタスク実行ポリシーをサポートします.
public interface Executor {

    /**
     * Executes the given command at some time in the future.  The command
     * may execute in a new thread, in a pooled thread, or in the calling
     * thread, at the discretion of the {@code Executor} implementation.
     *
     * @param command the runnable task
     * @throws RejectedExecutionException if this task cannot be
     * accepted for execution
     * @throws NullPointerException if command is null
     */
    void execute(Runnable command);
}

Executor:タスク、すなわちRunnableインタフェースを実現するクラスを実行するためのRunableインスタンスを受信するexecutorメソッドは、一般に、新しいスレッドでRunnableタスクを開くためのメソッドは、new Thread(new RunnableTask()である.start()ですが、Executorでは、表示することなくExecutorを使用してスレッド:executorを作成できます.execute(new RunnableTask());//非同期実行
ExecutorService:Executorよりも広く使用されているサブクラスインタフェースです.これにより、ライフサイクル管理の方法(ExecutorServiceのライフサイクルの3つのステータス:実行、停止、終了)、Futureオブジェクトに戻り、1つ以上の非同期タスクの実行状況を追跡してFutureに戻る方法が提供されます.shutdown()メソッドを呼び出してExecutorServiceをスムーズに閉じることができます.このメソッドを呼び出すと、ExecutorServiceは新しいタスクの受け入れを停止し、コミットされたタスクの実行が完了するのを待つことになります(コミットされたタスクは、すでに実行されているクラスと、まだ実行されていないクラスの2つに分類されます).コミットされたすべてのタスクが実行されると、ExecutorServiceが閉じます.shutdownNowメソッドでは、乱暴なクローズプロセスが実行されます.実行中のすべてのタスクをキャンセルし、キュー内でまだ実行が開始されていないタスクを開始しません.したがって,このインタフェースを用いてマルチスレッドを実装および管理するのが一般的である.ExecutorService.submit()メソッドが返すFutureオブジェクトは、isDone()メソッドを呼び出してFutureが完了したかどうかを問い合わせることができます.タスクが完了すると、get()メソッドを呼び出して結果を取得できます.isDone()をチェックせずにget()を直接呼び出して結果を取得することもできます.この場合、get()は結果の準備が整うまでブロックされ、タスクの実行をキャンセルすることもできます.Futureでは、pendingでのタスクの実行をキャンセルするためのcancel()メソッドが用意されています.
public interface ExecutorService extends Executor {
	//        
	void shutdown();
	List shutdownNow();
	boolean isShutdown();
	boolean isTerminated();
	boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException;
	//      
	 Future submit(Callable task);
	 Future submit(Runnable task, T result);
	 List> invokeAll(Collection extends Callable> tasks, long timeout, TimeUnit unit) throws InterruptedException;
}

Executors:スレッドプールの操作を提供します.Executosのスタティックファクトリメソッドの1つを呼び出してスレッドプールを作成する:newFixedThreadPool:固定長のスレッドプールを作成し、タスクをコミットするたびにスレッドプールの最大数に達するまでスレッドを作成します.これはスレッドプールの規模が変化しないことです(予期せぬExceptionが発生したためにスレッドが終了すると、スレッドプールに新しいスレッドが追加されます).新CachedThreadPool:キャッシュ可能なスレッドプールが作成されます.スレッドプールの現在の規模が処理要件を超えると、空きスレッドが回収されますが、要件が増加すると、新しいスレッドを追加できます.スレッドプールの規模には制限はありません.新SingleThreadExecutor:タスクを実行するために単一の作業者スレッドを作成する単一のスレッドのExecutor.このスレッドが異常に終了すると、代替の別のスレッドが作成されます.新SingleThreadExecutorは、タスクがキュー内にある順序でシリアルに実行されることを保証します.新ScheduledThreadPool:Timerと同様に、一定長のスレッドプールを作成し、遅延またはタイミングでタスクを実行します.
ExecutorとExecutorServiceの主な違い:1.ExecutorServiceインタフェースはExecutorインタフェースを継承し、Executorのサブインタフェースである.Executerインタフェースは、Runnableインタフェースのオブジェクトを受信するためにexecute()メソッドを定義し、ExecuterServiceインタフェースのsubmit()メソッドはRunnableインタフェースとCallableインタフェースのオブジェクトを受け入れることができます.3.Executerのexecute()メソッドは結果を返さず、ExecuterServiceのsubmit()メソッドは、Futureオブジェクトを使用して演算結果を返すことができます.4.クライアントがタスクを送信できるようにするだけでなく、ExecutorServiceはスレッドプールを制御する方法も提供します.たとえば、shutDown()メソッドを呼び出してスレッドプールを終了します.
CompletionService:非同期非ブロックパラレルタスク実行結果を取得します.CompletionServiceは、Executor(非同期スレッド)とBlockingQueue(キュー)の機能を融合させ、Callableタスクをコミットして実行し、キュー操作に似たtakeやpollなどの方法で完了した結果を得ることができます.このクラスでは、各スレッドの結果をすぐに取得できます.
	//      
    ExecutorService threadPool = Executors.newFixedThreadPool(10);
    //    
    CompletionService completionService = new ExecutorCompletionService(threadPool);
    for (int j = 1; j <= 5; j++) {

        final int index = j;
        completionService.submit(new Callable() {
            @Override
            public Integer call() throws Exception {
                //         
                if (index == 3) {
                    java.lang.Thread.sleep(3000l);
                }
                return index;
            }
        });
    }
    threadPool.shutdown();

    for (int i = 0; i < 5; i++) {
        try {
            System.out.println("  :"+completionService.take().get()+"       :");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }


取得結果は無秩序であり,3番目のスリープスレッドは常に最後に終了し,取得結果の方式が非ブロックであることも確認された.スレッド:2タスク実行終了スレッド:1タスク実行終了スレッド:5タスク実行終了スレッド:4タスク実行終了スレッド:3タスク実行終了
記事の参考:https://blog.csdn.net/weixin_40304387/article/details/80508236 https://blog.csdn.net/woshilijiuyi/article/details/78970497