パフォーマンスチューニングで便利! Callableクラスを使った並列処理

 
こんにちは。ぐっさんです。

Webシステムにおいて、パフォーマンスというのは、エンジニアにとって悩みの種だと思います。
そこで、今回ご紹介するのがCallableクラスを使った並列処理です。
だいぶ昔からJavaで用意されていますが、こちらを利用することで、複数の処理を並列して実行することができます。

10個の処理を5スレッドで実行したサンプルは、下記の通りです。

package jp.amg_solution.blog.sample.callable;

import java.util.Date;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class CallableSample {

	public static void main(String[] args) {
		System.out.println("CallableSample start.");

		// 1.Executorクラスの生成:引数にスレッド数を渡す。
		ExecutorService executorService = Executors.newFixedThreadPool(5);

		for (int i=0; i<10; i++) {
			// 2.Callableクラスのcallメソッドを実装して、Taskリストに登録
			executorService.submit(new Callable<Boolean>() {
				@Override
				public Boolean call() throws Exception {
					Date now = new Date();
					System.out.println(now + " [THREAD_ID] " + Thread.currentThread().getId());
					Thread.sleep(2000);
					return true;
				}
			});
		}

		// 3.実行サービスを終了
		executorService.shutdown();
		System.out.println("CallableSample end.");
		return;
	}
}

1.Executorクラスに実行スレッド数を渡して、インスタンスを生成します。
2.Callbleクラスのcallメソッドを実装して、Taskリストに登録します。
3.実行サービスを終了します。

実行結果は、下記の通りです。

>java jp.amg_solution.blog.sample.callable.CallableSample
CallableSample start.
CallableSample end.
Thu Oct 01 19:36:14 JST 2015 [THREAD_ID] 11
Thu Oct 01 19:36:14 JST 2015 [THREAD_ID] 9
Thu Oct 01 19:36:14 JST 2015 [THREAD_ID] 12
Thu Oct 01 19:36:14 JST 2015 [THREAD_ID] 10
Thu Oct 01 19:36:14 JST 2015 [THREAD_ID] 13
Thu Oct 01 19:36:16 JST 2015 [THREAD_ID] 13
Thu Oct 01 19:36:16 JST 2015 [THREAD_ID] 9
Thu Oct 01 19:36:16 JST 2015 [THREAD_ID] 12
Thu Oct 01 19:36:16 JST 2015 [THREAD_ID] 10
Thu Oct 01 19:36:16 JST 2015 [THREAD_ID] 11

CallableSampleクラスの実行が終わってもスレッド処理が実行されていることが分かります。

スレッド処理を待ってから、処理を実行したい場合もあると思います。
その時は、Taskリストを用意することで、処理を待つことができます。
スレッド処理を待つサンプルは、下記の通りです。

package jp.amg_solution.blog.sample.callable;

import java.util.ArrayList;
import java.util.Date;
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;

public class CallableSample {

	public static void main(String[] args) {
		System.out.println("CallableSample start.");

		// Executorクラスの生成:引数にスレッド数を渡す。
		ExecutorService executorService = Executors.newFixedThreadPool(5);
		// 各スレッドの処理を待つためのTaskリストを用意
		List<Future<Boolean>> submitTaskList = new ArrayList<Future<Boolean>>();

		for (int i=0; i<10; i++) {
			// 2.Callableクラスのcallメソッドを実装して、Taskリストに登録
			submitTaskList.add(executorService.submit(new Callable<Boolean>() {
				@Override
				public Boolean call() throws Exception {
					Date now = new Date();
					System.out.println(now + " [THREAD_ID] " + Thread.currentThread().getId());
					Thread.sleep(2000);
					return true;
				}
			}));
		}

		// 3.スレッド処理を待つ
		try {
			for (Future<Boolean> future : submitTaskList) {
				if (future.get() == false) {
					throw new RuntimeException("スレッド処理エラー");
				}
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		} catch (ExecutionException e) {
			e.printStackTrace();
		}

		// 4.実行サービスを終了
		executorService.shutdown();
		System.out.println("CallableSample end.");
		return;
	}
}

1.Executorクラスに実行スレッド数を渡して、インスタンスを生成します。
2.Callbleクラスのcallメソッドを実装して、Taskリストに登録します。
3.スレッド処理を待って、結果を受け取ります。
4.実行サービスを終了します。

実行結果は、下記の通りです。

>java jp.amg_solution.blog.sample.callable.CallableSample
CallableSample start.
Thu Oct 01 19:31:33 JST 2015 [THREAD_ID] 13
Thu Oct 01 19:31:33 JST 2015 [THREAD_ID] 9
Thu Oct 01 19:31:33 JST 2015 [THREAD_ID] 12
Thu Oct 01 19:31:33 JST 2015 [THREAD_ID] 10
Thu Oct 01 19:31:33 JST 2015 [THREAD_ID] 11
Thu Oct 01 19:31:35 JST 2015 [THREAD_ID] 9
Thu Oct 01 19:31:35 JST 2015 [THREAD_ID] 12
Thu Oct 01 19:31:35 JST 2015 [THREAD_ID] 13
Thu Oct 01 19:31:35 JST 2015 [THREAD_ID] 11
Thu Oct 01 19:31:35 JST 2015 [THREAD_ID] 10
CallableSample end.

スレッド処理が終わってからCallableSampleクラスの実行が終わっていることが分かります。

パフォーマンスチューニングを行う際の1つの手段として、並列処理は有効です。
また、試してみたい方は、サンプルプログラムをブログ内でコピーできますので、試してみてください。

よいパフォーマンスチューニングライフを!

記事をシェア
MOST VIEWED ARTICLES