При таком подходе ExecutorService сначала прекратит принимать новые задачи, подождет определенный период времени для завершения всех задач.
Если в течении этого времени задачи не завершатся, вызвать метод shutdownNow, который прервет все выполняемые задачи и немедленно завершит работу ExecutorService.
Здесь, в этом примере, та же самая ситуация, только одновременно создаются две задачи, которые помещаются в очередь на выполнение.
Вместо использования объекта Runnable, так как использование Runnable ограничено тем, что задачи не могут вернуть результат, для создания задачи можно использовать объект Callable, который позволяет задаче вернуть результат.
Если в Runnable мы определяем метод run, то в Callable, мы определяем метод call.
Метод submit помещает задачу в очередь для выполнения потоком.
Однако он не знает, когда будет получен результат этой задачи.
Поэтому он возвращает специальный тип значения, называемый Future, который может использоваться для извлечения результата задачи, когда этот результат будет доступен.
Метод ExecutorService.submit немедленно возвращает объект Future.
После того, как вы получили Future, вы можете выполнять другие задачи параллельно во время выполнения поставленной задачи, а затем использовать метод future.get для получения результата.
Обратите внимание, метод get устанавливает блокировку текущего потока до тех пор, пока не завершится выполнение задачи.
Future также предоставляет метод isDone для проверки того, завершена задача или нет.
Если прерывается поток, выполняющий вычисление, метод генерирует исключение InterruptedException.
Когда вычисление задачи завершается, метод get немедленно возвращает управление.
Вы можете отменить Future, используя метод Future.cancel, который пытается отменить выполнение задачи и возвращает true, если она отменена успешно, иначе метод возвращает false.
Метод cancel принимает логический аргумент, и если вы передадите значение true для этого аргумента, то поток, который в настоящее время выполняет задачу, будет сразу прерван, в противном случае выполнение задачи может быть завершено.
Вы можете использовать метод isCancelled, чтобы проверить задача отменена или нет.
Кроме того, после отмены задачи, метод isDone всегда будет возвращать true.
Метод future.get блокирует и ждет завершения задачи.
Если, вы вызываете удаленную службу в задаче, а удаленная служба отключена, то future.get заблокирует приложение навсегда.
Чтобы это предотвратить, вы можете добавить в метод get время ожидания.
Также, как и с объектом Runnable, с помощью объекта Callable, вы можете одновременно создать сразу несколько задач и отправить их на выполнение.
Обратите внимание, что, во-первых, здесь мы создаем фиксированный пул из двух потоков.
Во-вторых, мы используем метод invokeAll, чтобы выполнить несколько задач, передавая коллекцию объектов Callable.
Метод invokeAll возвращает список объектов Future.
Метод invokeAll ожидает, пока все результаты не будут вычислены до их возврата. То есть метод invokeAll возвращает список объектов Future, для которых isDone true.
В отличие от метода submit, который возвращает сразу, метод invokeAll ожидает завершения задач.
Так как метод invokeAll возвращает коллекцию, ее можно обработать с помощью Stream API.
В отличие от метода invokeAll, метод invokeAny передает на выполнение список задач и ожидает выполнение любой из них, то есть наиболее быстрой.
Для выполнения задачи либо периодически, либо после указанной задержки, можно использовать ScheduledExecutorService.
Здесь метод schedule принимает объект Runnable, задержку и единицу задержки, и определяет выполнение задачи через 5 секунд с момента отправки.
Метод scheduleAtFixedRate принимает объект Runnable, начальную задержку, период выполнения и единицу времени, и запускает выполнение заданной задачи после указанной задержки и затем периодически выполняет ее с указанным интервалом.
Имейте в виду, что scheduleAtFixedRate не учитывает фактическую продолжительность задачи. Поэтому, если вы укажете период в одну секунду, но для выполнения задачи потребуется 2 секунды, тогда пул потоков начнет быстро перегружаться.
Поэтому для периодического запуска задачи лучше использовать метод scheduleWithFixedDelay.
Разница заключается в том, что период ожидания применяется от конца задачи до начала следующей задачи.
В этом примере задача выполняется периодически с фиксированной задержкой в одну секунду между окончанием выполнения и началом следующего выполнения.
Чтобы удалить задачу без остановки ScheduledExecutorService, можно использовать результат ScheduledFuture, возвращаемый методами интерфейса ScheduledExecutorService, и применить к этому результату метод cancel.
Для возврата результата, в метод schedule можно передать не объект Runnable, а объект Callable, и применить к результату ScheduledFuture метод get, так как ScheduledFuture расширяет уже знакомый нам интерфейс Future.
Вильям Л Саймон , Вильям Саймон , Наталья Владимировна Макеева , Нора Робертс , Юрий Викторович Щербатых
Зарубежная компьютерная, околокомпьютерная литература / ОС и Сети, интернет / Короткие любовные романы / Психология / Прочая справочная литература / Образование и наука / Книги по IT / Словари и Энциклопедии