обработка асинхронного выключения исполнителя при ожидании на будущее - PullRequest
0 голосов
/ 05 мая 2018

У меня есть реализация клиентской библиотеки ssh. Каждое соединение имеет несколько исполнителей. Одним из них является пул потоков, использующий ScheduledThreadPoolExecutor, который используется для постановки в очередь краткосрочных задач и таймеров. Одним из них является исполнитель чтения, используемый для хранения задачи приема пакетов. Одним из них является исполнитель записи, последовательно выполняющий задачи, каждая из которых отправляет один пакет на сервер. Конечно, исполнитель чтения и записи является однопоточным, а исполнитель записи используется как нечто вроде очереди сообщений.

Проблема, с которой я столкнулся: методы для очереди сообщений и некоторые методы для задач, возвращающих CompletableFuture. Я ставлю вещи в очередь с помощью метода CompletableFuture.runAsync. Однако соединение может быть асинхронно закрыто упорядоченным или принудительным образом. В этом случае некоторые или все пулы отключаются с помощью метода shutdownNow.

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

Как лучше всего справляться с этой ситуацией? Что люди делают / и т.д.?

1 Ответ

0 голосов
/ 05 мая 2018

Хорошо, я думаю, у меня есть идея. это следующее:

Поскольку параллельное завершение работы ожидает завершения всех задач, а shutdownNow просто удаляет их без отмены, а поскольку я фактически все время использую завершаемые фьючерсы, я решил поддерживать набор завершаемых фьючерсов всех видов на соединение, он будет содержать все задачи, включая отправителей сообщений и обычные задачи, отправленные в пул задач. Каждый метод, который закрывает соединение или начинает упорядоченное разъединение, проходит через набор и завершает все фьючерсы исключительно с некоторым исключением. Это дает лучшие ошибки, чем отмена. Также ничего не должно произойти, если задача сама себя отменит.

Вместо использования runAsync или обычного создания завершаемого будущего в случае задач, не связанных с выполняемыми таблицами, у меня есть специальный метод, который создает такую ​​задачу, добавляет ее в набор и присоединяет функцию с помощью CompletableFuture.whenCompleted () , который удаляет задание из набора, если оно выполнено по какой-либо причине. У меня также есть runAsync, который создает задачу с использованием ранее описанного метода, а затем отправляет исполняемый файл с использованием CompletableFuture.completeAsync.

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

...