第46回 マルチスレッド編CallableインターフェースRunnableFutureインターフェース
今回のテーマは「CallableとRunnableFuture」です。
CallableインターフェースはRunnableインターフェース同様マルチスレッドプログラムのためのインターフェースです。 マルチスレッドプログラムを作成する場合、Runnableインターフェースを実装し、Threadクラスのstartメソッドを実行するのが一般的でしょう。 しかし、Runnableインターフェースのrunメソッドには戻り値がない、例外をスローできないなどの制限がありました。
Callableインターフェースを実装するクラスはcallメソッドを実装する必要があります。 callメソッドは任意の戻り値を指定でき、例外をスローすることができます。
Callableを実行する方法はいくつかありますが、今回はおなじみのThreadクラスを使って実行してみたいと思います。
次のサンプルコードはファイルを読み込むタスクを実行し、読み込んだ結果を出力するプログラムです。(J2SE6.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.FutureTask; import java.util.concurrent.RunnableFuture; public class Main { public static void main(String[] args) throws Exception { File file = new File("input.csv"); RunnableFuture<List<String>> runnableFuture = new FutureTask<List<String>>(new ICallable(file)); new Thread(runnableFuture).start(); List<String> list = runnableFuture.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; } }
RunnableFutureインターフェースはRunnableインターフェースとFutureインターフェースのサブインターフェースです。
RunnableFutureの実装クラスであるFutureTaskはCallableオブジェクトをラップし、Runnableとして扱うことができます。
Futureは非同期処理の結果を表すインターフェースです。
したがって、FutureTaskはCallableを実行し、その結果を保持することができます。
getメソッドは必要に応じて計算が完了するまで待機し、結果を取得します。
ファイルの読み込みが完了するまで処理が進行しないように同期しています。