第47回 マルチスレッド編ExecutorServiceインターフェース
今回のテーマは「ExecutorService」です。
前回はThreadクラスを使用してマルチスレッドプログラムを作成しましたが、Threadクラスを意識することなくマルチスレッドプログラムを作成するためのExecutorというインターフェースがあります。 非同期処理がどのように実行されるかは、Executorインターフェースの実装次第なので、その実装による拡張がなされています。 例えば、ExecutorインターフェースのサブインターフェースであるExecutorServiceインターフェースは非同期処理の結果の生成、複数のタスクの一括実行などをサポートします。 ExecutorServiceインターフェースを実装するクラスにはThreadPoolExecutorなどがあります。 ThreadPoolExecutorはスレッドをプールし、非同期処理を効率的に実行します。
ExecutorServiceを使用する場合、独自でThreadPoolExecutorを生成するより、Executorsクラスのファクトリメソッドを使用することが推奨されています。 newCachedThreadPoolメソッドは必要に応じ、新規スレッドを作成するスレッドプールを作成します。 newFixedThreadPoolメソッドは固定数のスレッドを再利用するスレッドプールを作成します。 newSingleThreadExecutorメソッドは単一のワーカースレッドを使用するExecutorを作成します。 これらのメソッドは一般的に使用される構成で設定されたExecutorServiceを返してくれます。
次のサンプルコードは前回と同様の処理をExecutorServiceを使用して実行するプログラムです。(J2SE5.0以上対応)
import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.util.LinkedList; 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 Main { public static void main(String[] args) throws Exception { File file = new File("input.csv"); ExecutorService executorService = Executors.newSingleThreadExecutor(); Future<List<String>> future = executorService.submit(new ICallable(file)); executorService.shutdown(); List<String> list = future.get(); for (String string : list) { System.out.println(string); } } } class ICallable implements Callable<List<String>> { private File file; public ICallable(File file) { this.file = file; } public List<String> call() throws Exception { List<String> list = new LinkedList<String>(); BufferedReader bufferedReader = null; try { bufferedReader = new BufferedReader(new FileReader(file)); while (bufferedReader.ready()) { list.add(bufferedReader.readLine()); } } finally { if (bufferedReader != null) { bufferedReader.close(); } } return list; } }
今回、ファイルを読み込むスレッドは1つなので、newSingleThreadExecutorメソッドを使用しExecutorServiceを取得しました。
Futureは非同期処理の結果を表すインターフェースです。
callメソッド内で例外が発生した場合、getメソッドが例外をスローするので、shutdownメソッドは実行されます。