JLesson 38. Многопоточность в Java. Часть 3. Executors.

Интерфейс Runnable представляет собой асинхронную задачу, которая не возвращает результат и не принимает никаких параметров. Но на практике вам может понадобиться все-таки получить из другого потока какой-нибудь результат вычисления определенного типа. Именно для этого и предназначен интерфейс — Callable, расположенный в пакете java.util.concurrent(более подробно о возможностях этой библиотеки мы поговорим в следующем уроке). Также, как и Runnable, он очень прост и имеет всего один метод call():

Данный интерфейс является параметризованным тем типом, который будет являться результатом выполнения задачи. Допустим, вы просто выполняет

е некие простые вычисления ,например, перемножаете два числа. Давайте создадим для этой задачи класс ComputeTask и реализуем в нем интерфейс Callable:

Наш класс параметризован типом Double — типом результата перемножения двух чисел, который мы хотим вернуть. Также нашей задаче нужно как-то передать параметры — операнды для умножения. Для этой цели мы можем создать в нашем классе конструктор, принимающий два операнда и дополнительные приватные поля для их хранения:

Теперь реализуем метод call():

Теперь осталось только запустить задачу на исполнение в отдельном потоке. Немного забегая вперед,  покажем, как это можно сделать при помощи исполнителя — объекта класса ExecutorService из того же пакета java.util.concurrent. Вообще интерфейс ExecutorService является расширением интерфейса Executor, который выполняет полученные ему задачи типа Runnable.

ExecutorService в отличие от него способен принимать задачи типа Callable<V> и возвращать результат в виде объектов Future<V>:

Итак, что мы делаем в нашем коде: сначала создаем исполнителя для нашей задачи, который запустит ее в отдельном потоке. Получаем мы его, используя статический метод класса Executors, еще одного вспомогательного класса-фабрики, который создает различных исполнителей для решения разных задач. В нем существуют отдельные методы для создания пула потоков, но нам сейчас для работы нужен только один поток, поэтому вызываем метод newSingleThreadExecutor().

Далее создаем нашу асинхронную задачу и отдаем ее на исполнение, передавая в метод submit(), который по окончании работы вернет нам результат выполнения задачи в виде объекта класса Future<V>. Данный объект просто хранит внутри себя результат асинхронных вычислений.

В блоке try мы получаем этот результат вызовом метода get(), уже в виде объекта типа Double. Также здесь обрабатываем возможные исключения.

После запуска программы, получим результат:

java_concurrency

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *