別スレッドにするタスクの作成
別にスレッドにしたい処理を、Runnable インタフェースを実装したクラスのrumメソッドに実装する。
public class TestRunnable implements Runnable { public void run() { // スレッドIDを出力する System.out.println(Thread.currentThread().getId()); } }
スレッドの生成とタスクの実行
ExecutorService クラスを利用して、スレッドの生成・タスクの実行を行う。
ここでは、「newSingleThreadExecutor」でスレッドを一つのみ生成し、5回タスクを実行している。
ExecutorService exec = Executors.newSingleThreadExecutor(); for (int i = 0; i < 5; i++) { exec.submit(new TestRunnable()); }
実行結果
1スレッドのみなので、すべて同じスレッドIDが出力される。
44
44
44
44
44
固定数の複数スレッド生成
newFixedThreadPoolを使用すると、固定数のスレッドを生成できる。
// 引数に生成するスレッド数を渡す
ExecutorService exec = Executors.newFixedThreadPool(3); for (int i = 0; i < 5; i++) { exec.submit(new TestRunnable()); }
3つの固定スレッドを生成したので、3つのスレッドを使いまわしている。
24
24
24
26
25
必要に応じて複数スレッド生成
newCachedThreadPoolを使用すると、必要に応じてスレッドを生成する。
60秒間使用されなかったスレッドは破棄され、60秒未満であれば再利用される。
ExecutorService exec = Executors.newCachedThreadPool(); for (int i = 0; i < 5; i++) { exec.submit(new TestRunnable()); } Thread.sleep(1 * 5000); System.out.println("--------5秒後---------"); for (int i = 0; i < 5; i++) { exec.submit(new TestRunnable()); } Thread.sleep(1 * 70000); System.out.println("--------70秒後---------"); for (int i = 0; i < 5; i++) { exec.submit(new TestRunnable()); }
3回に分けて処理を実行。
最初の実行から、5秒後に実行した処理は同じスレッドを再利用している。
70秒後の実行では既にスレッドが破棄されて、新しいスレッドが生成されている。
26
24
25
27
28
--------5秒後---------
24
27
28
25
26
--------70秒後---------
31
33
30
32
29
実行結果を取得する
実行結果を返すタスクの作成
実行結果を返す処理は、Callableインタフェースを実装したクラスのcallメソッドに実装する。
public class TestCallable implements Callable<Long> { public Long call() throws Exception { //スレッドIDを返す return Thread.currentThread().getId(); } }
タスクの実行と実行結果の取得
タスクの実行は、結果を返さない場合と同じく ExecutorService を使用するが、
戻り値としてFutureインタフェースを受け取る。
List<Future<Long>> list = new ArrayList<Future<Long>>(); for (int i = 0; i < 10; i++) { Future<Long> future = exec.submit(new TestCallable()); list.add(future); } //Future#getメソッドで結果を取得できる。実行中の場合は終了まで待つ。 for (Future<Long> future : list) { try { Long id = future.get(); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } }
引数を指定することで、指定した時間だけ実行結果を待つことができる。
指定した時間を超えると、TimeoutExceptionがスローされる。
//1秒間だけ待つ。
Long id = future.get(1, TimeUnit.SECONDS);