Future и FutureTask

Future и FutureTask

Future<V> - это интерфейс, представляющий результат асинхронного вычисления - тот результат, который будет получен в будущем после выполнения задачи. Методы, выполнение которых занимает довольно много времени, хорошие кандидаты для асинхронной обработки. Использование интерфейса Future позволяет потоку не простаивать во время ожидания завершения метода, инкапсулированного в Future, а выполнять какую-нибудь полезную работу.

Класс FutureTask<V> - реализация интерфейса Future<V>. Для создания объекта FutureTask в его конструктор нужно передать объект типа Callable<V>. При этом FutureTask реализует ещё и интерфейс RunnableFuture<V>. Таким образом, FutureTask представляет удобный механизм для превращения Callable одновременно в Future и Runnable, реализуя оба интерфейса.

Проверить, завершена ли задача, можно вызовом метода isDone() - вернёт true, если задача завершена или прервана.
Получить результат выполнения задачи можно вызовом метода get() - блокирующий метод, вернёт управление вызвавшему потоку только после завершения выполнения задачи.


class Fibonacci implements Callable<int[]> {
    private int digit;
    private int[] fibonacciNumber;

    Fibonacci(int digit) {
        this.digit = digit;
        fibonacciNumber = new int[digit];
    }

    @Override
    public int[] call() throws Exception {
        for (int i = 1; i <= digit; i++) {
            fibonacciNumber[i - 1] = compute(i);
        }
        System.out.println("Fibonacci number is built");
        return fibonacciNumber;
    }

    private int compute(int x) {
        if (x == 1 || x == 2) {
            return 1;
        }
        return (compute(x - 2) + compute(x - 1));
    }
}


public class Main {

    public static void main(String[] args) throws Exception {
        Fibonacci f = new Fibonacci(10);
        FutureTask<int[]> task = new FutureTask<>(f);

        ExecutorService executor = Executors.newSingleThreadExecutor();
        executor.execute(task);

        if (!task.isDone()) {
            System.out.println("Waiting for completing task...");
        } 

        doSomeUseful(2000);

        int[] fibonacciNumber = task.get();
        StringBuilder sb = getReadableViewFibonacciNumber(fibonacciNumber);
        System.out.println(sb);

        executor.shutdown();
    }

    private static StringBuilder getReadableViewFibonacciNumber(int[] fibonacciNumber) {
        StringBuilder sb = new StringBuilder();
        String separator = " + ";
        for (int fib : fibonacciNumber) {
            sb.append(fib);
            sb.append(separator);
        }
        sb.setLength(sb.length() - separator.length());
        return sb;
    }

    private static void doSomeUseful(int interval) {
        try {
            Thread.sleep(interval);
            System.out.println("Some useful is done");
        } catch (InterruptedException ex) {
            ex.printStackTrace(System.out);
        }
    }
}


/*
Waiting for completing task...
Fibonacci number is built
Some useful is done
1 + 1 + 2 + 3 + 5 + 8 + 13 + 21 + 34 + 55
 */
Многопоточность