基本パターン(単一スレッド)
別スレッドにするタスクの作成
別にスレッドにしたい処理を、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);