Java ExecutorServiceの例

Javaでは、 ExecutorService`を使用してスレッドプールを作成し、 Future`を使用して非同期タスクの進行状況を追跡できます。

ExecutorService`は Runnable`と `Callable`タスクの両方を受け入れます。

  1. Runnable - 何も返さない.

  2. 呼び出し可能 - 将来を返す

1. ExecutorService

1.1 5つのスレッドを持つスレッドプールを作成し、2つのタスクを実行し、 Future`から結果を取得し、例外を処理する古典的な ExecutorService`の例です。

ExecutorExample1.java

package com.mkyong.concurrency.executor;

import java.util.concurrent.** ;

public class ExecutorExample1 {

    public static void main(String[]args) {

        ExecutorService executor = Executors.newFixedThreadPool(5);

       //Runnable, return void, nothing, submit and run the task async
        executor.submit(() -> System.out.println("I'm Runnable task."));

       //Callable, return a future, submit and run the task async
        Future<Integer> futureTask1 = executor.submit(() -> {
            System.out.println("I'm Callable task.");
            return 1 + 1;
        });

       /**  Before Java 8
        executor.submit(new Runnable() {
            @Override
            public void run() {
                System.out.println("I'm Runnable task.");
            }
        });

        Future<Integer> futureTask1 = executor.submit(new Callable<Integer>() {
            @Override
            public Integer call() {
                System.out.println("I'm Callable task.");
                return 1 + 1;
            }
        });** /
        try {

            otherTask("Before Future Result");

           //block until future returned a result,
           //timeout if the future takes more than 5 seconds to return the result
            Integer result = futureTask1.get(5, TimeUnit.SECONDS);

            System.out.println("Get future result : " + result);

            otherTask("After Future Result");


        } catch (InterruptedException e) {//thread was interrupted
            e.printStackTrace();
        } catch (ExecutionException e) {//thread threw an exception
            e.printStackTrace();
        } catch (TimeoutException e) {//timeout before the future task is complete
            e.printStackTrace();
        } finally {

           //shut down the executor manually
            executor.shutdown();

        }

    }

    private static void otherTask(String name) {
        System.out.println("I'm other task! " + name);
    }
}

出力

I'm Runnable task.
I'm Callable task.
I'm other task! Before Future Result
Get future result : 2
I'm other task! After Future Result

2. invokeAll

2.1 Callable`タスクのリストを作成し、 invokeAll`を使ってそれらをすべて実行することもできます

ExecutorExample2.java

package com.mkyong.concurrency.executor;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class ExecutorExample2 {

    public static void main(String[]args) {

        ExecutorService executor = Executors.newCachedThreadPool();

        List<Callable<Integer>> listOfCallable = Arrays.asList(
                () -> 1,
                () -> 2,
                () -> 3);

        try {

            List<Future<Integer>> futures = executor.invokeAll(listOfCallable);

            int sum = futures.stream().map(f -> {
                try {
                    return f.get();
                } catch (Exception e) {
                    throw new IllegalStateException(e);
                }
            }).mapToInt(Integer::intValue).sum();

            System.out.println(sum);

        } catch (InterruptedException e) {//thread was interrupted
            e.printStackTrace();
        } finally {

           //shut down the executor manually
            executor.shutdown();

        }

    }

}

出力

6

ソースコードをダウンロードする

参考文献

並行処理 executor リンク://タグ/java/[java]リンク://タグ/java-thread/[javaスレッド] スレッドプール