スレッドで戻り値を取得する方法

ほしがき2017/10/15(日) - 11:36 に投稿

Javaでスレッドで処理する方法はいくつかあります。

Threadを継承、Runnableを実装などなど。

これらの方法は戻り値を取得できないため、実装する際は楽ではあるけども中々不便です。

その処理成功したの?失敗したの?わからんぞ!と。

やりっぱなしでOKなものであれば問題ないですけどね。

今回は戻り値を取得する方法をメモります。

ついでに立ち上げるスレッド数の指定も行います。

 

実行環境


  • Windows10 Pro
  • eclipse 4.7
  • java8

 

使用するクラス


使用するのは以下のクラスです。

Callableのcallメソッドを実装した処理クラスをExecutorsServiceで実行していきます。

実行にはExecutorsService#submitを使用し、戻り値もこのメソッドで取得可能です。

 

実装してみる


 

まずはCallableを実装したTestCallableのソースです。

適当にスリープ入れてます。

package thread.test;

import java.util.Random;
import java.util.concurrent.Callable;

public class TestCallable implements Callable<Integer> {

    private int i = 0;
    public TestCallable(int count) {
        i = count;
    }

    @Override
    public Integer call() {

        try {
            Random random = new Random();
            Thread.sleep(random.nextInt(1000));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return i;
    }
}

 

上記スレッドを起動するメインクラスです。

今回はExecutors.newFixedThreadPool(int nThreads)でスレッド数の指定も行っています。

引数に渡す値分スレッドを起動してくれます。

このクラスではservice.submit(test)でスレッドを起動し、戻り値のFuture<?>のListに追加しています。

Future<?>にスレッドクラスであるTestCallable#callの実行結果が入ってきます。

実行結果を取得するメソッドがFuture#getとなりますが、このgetメソッドは処理が完了するまで待機されるので一旦リストに入れてスレッドを起動できる状態に持って行った後に結果を待った方が良いでしょう。

つまり、

service.submit(test))

service.submit(test).get()

とかしちゃうのはやめましょうってことです。

実行は実行、結果取得は結果取得でわけましょう。

package thread.test;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class ThreadTest {

    public static void main(String[] args) {

        ExecutorService service = Executors.newFixedThreadPool(4);

        List<Future<Integer>> retList = new ArrayList<>();

        for (int i = 0; i < 10; i++) {
            TestCallable test = new TestCallable(i);
            retList.add(service.submit(test));
        }

        for (int i = 0; i < retList.size(); i++) {
            Future<Integer> num = retList.get(i);

            try {
                System.out.println(num.get());
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }
        service.shutdown();
    }
}

処理結果としては普通に0から9まで順々に表示されるだけです。

以上です。

 

 

 

 

 

タグ