Интерфейсы Callable и Future в Java

Интерфейсы Callable и Future в JavaИнтерфейс Runnable инкапсулирует задачу, выполняющуюся асинхронно. Вы можете воспринимать это как асинхронный метод без параметров и возвращаемого значения. Callable подобен Runnable, но с возвратом значения. Интерфейс Callable является параметризованным типом, с единственным общедоступным методом call().

Параметр представляет собой тип возвращаемого значения. Например, Callable представляет асинхронное вычисление, которое в конечном итоге возвращает объект Integer.

Future хранит результат асинхронного вычисления. Вы можете запустить вычисление, предоставив кому-либо объект Future, и забыть о нем. Владелец объекта Future может получить результат, когда он будет готов.

Интерфейс Future имеет следующие методы.

Вызов первого метода get() устанавливает блокировку до тех пор, пока не завершится вычисление. Второй метод генерирует исключение TimeoutException, если истекает таймаут до завершения вычислений. Если прерывается поток, выполняющий вычисление, оба метода генерируют исключение InterruptedException. Если вычисление уже завершено, get() немедленно возвращает управление.

Метод isDone() возвращает false, если вычисление продолжается, и true — если оно завершено.

Вы можете прервать вычисление,вызвав метод Cancel(). Если вычисление еще не стартовало, оно отменяется и уже не будет запущено. Если же вычисление уже идет, оно прерывается в случае равенства true параметра mayInterrupt.

Любите задавать вопросы в Аске, но Вам не хватает подписчиков и лайков — попробуйте заказать их на сервисе avi1.ru. Здесь Вы получите данные ресурсы по очень дешевой стоимости, а также с высококачественным исполнением от лучших сотрудников техподдержки.

Класс-оболочка FutureTask представляет собой удобный механизм для превращения Callable одновременно в Future и Runnable, реализуя оба интерфейса.

Например:

Программу которую вы увидите ниже демонстрирует эту концепцию в действии. Мы просто будем подсчитывать количество файлов, соответствующих критерию поиска. Таким образом, у нас будет долго работающая задача, которая в результате даст целочисленное значение — пример Callable.

Сконструируем объект из MatchCounter и используем его для запуска потока:

И, наконец, напечатаем результат:

Конечно, вызов get() устанавливает блокировку до тех пор, пока не будет готов результат.

Внутри метода call() мы используем тот же механизм рекурсивно. Для каждого подкаталога создадим новый MathCounter и запустим поток для него. Также мы спрячем объект FutureTask в ArrayList<Future>. И в конце сложим все результаты:

Каждый вызов get() устанавливает блокировку до тех пор, пока не будет готов результат. Конечно, потоки работают параллельно, так что есть шанс, что результаты будут готовы почти одновременно.

Вот полный код нашей программы: