JavaでExecutorServiceを使用して並列処理・逐次処理をする

JavaでExecutorServiceを使用して並列処理・逐次処理をする

並列処理

並列処理を行う場合newFixedThreadPoolメソッドでインスタンスを作成します。引数で並列処理数を設定します。

以下、5つの処理を5つのスレッドで実行します。Futureオブジェクトで同期しています。

package jp.co.confrage;

import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

public class ExecutorSample {
  static int TASK_COUNT = 5;
  static int POOL_SIZE = 5;

  public static void main(String... args) throws InterruptedException, ExecutionException {
    ExecutorService executor = Executors.newFixedThreadPool(POOL_SIZE);
    List<Callable<String>> tasks = new LinkedList<Callable<String>>();
    for (int i = 0; i < TASK_COUNT; i++) {
      tasks.add(new Task(i));
    }
    try {
      List<Future<String>> futures = executor.invokeAll(tasks); // 実行

      for (int i = 0; i < TASK_COUNT; i++) {
        String result = (futures.get(i)).get();
        System.out.println(result);
      }
    } finally {
      if (!executor.isShutdown()) executor.shutdown();
      if (!executor.isTerminated()) executor.awaitTermination(1, TimeUnit.MINUTES);
    }
  }
}

class Task implements Callable<String> {
  private int number;
  /** コンストラクタ */
  public Task(int number) {
    this.number = number;
  }

  /**
   * 重い処理
   *
   * @return レスポンス
   * @see java.util.concurrent.Callable#call()
   */
  @Override
  public String call() throws Exception {
    if (this.number == 0) {
      Thread.sleep(2000); // 2秒かかる
    } else {
      Thread.sleep(5000); // 5秒かかる
    }
    return number + " : OK";
  }
}

結果は以下のようになります。

0 : OK
1 : OK
2 : OK
3 : OK
4 : OK ★約5秒強

逐次処理

逐次処理を行う場合はnewSingleThreadExecutorメソッドでインスタンスを作成します。引数はありません。1つのスレッドで処理を行います。

package jp.co.confrage;

import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

public class ExecutorSample {
  static int TASK_COUNT = 5;
  public static void main(String... args) throws InterruptedException, ExecutionException {
    ExecutorService executor = Executors.newSingleThreadExecutor();
    List<Callable<String>> tasks = new LinkedList<Callable<String>>();
    for (int i = 0; i < TASK_COUNT; i++) {
      tasks.add(new Task(i));
    }
    try {
      List<Future<String>> futures = executor.invokeAll(tasks); // 実行

      for (int i = 0; i < TASK_COUNT; i++) {
        String result = (futures.get(i)).get();
        System.out.println(result);
      }
    } finally {
      if (!executor.isShutdown()) executor.shutdown();
      if (!executor.isTerminated()) executor.awaitTermination(1, TimeUnit.MINUTES);
    }
  }
}

class Task implements Callable<String> {
  private int number;
  /** コンストラクタ */
  public Task(int number) {
    this.number = number;
  }

  /**
   * 重い処理
   *
   * @return レスポンス
   * @see java.util.concurrent.Callable#call()
   */
  @Override
  public String call() throws Exception {
    if (this.number == 0) {
      Thread.sleep(2000); // 2秒かかる
    } else {
      Thread.sleep(5000); // 5秒かかる
    }
    return number + " : OK";
  }
}

結果は以下のようになります。

0 : OK
1 : OK
2 : OK
3 : OK
4 : OK ★約22秒強

リストに詰めた処理順に順次実行されます。前の処理が終わるまで後続の処理は待ちます。

コメント

タイトルとURLをコピーしました