基本パターン(単一スレッド)

 

別スレッドにするタスクの作成

別にスレッドにしたい処理を、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);
原文地址:https://www.cnblogs.com/xpvincent/p/7753968.html