Как лучше обрабатывать исключения (необработанные) при использовании ForkJoinPool
для отправки задач (RecursiveAction
или RecursiveTask
)?
ForkJoinPool принимает Thread.UncaughtExceptionHandler
для обработки исключений, когда WorkerThread завершается внезапно (что в любом случае не находится под нашим контролем), но этот обработчик не используется, когда ForkJoinTask
выдает исключение.В своей реализации я использую стандартный submit
/ invokeAll
.
Вот мой сценарий:
У меня есть темаработает в бесконечном цикле чтения данных из сторонней системы.В этой теме я отправляю Задачи в ForkJoinPool
new Thread() {
public void run() {
while (true) {
ForkJoinTask<Void> uselessReturn =
ForkJoinPool.submit(RecursiveActionTask);
}
}
}
Я использую RecursiveAction и в некоторых случаях RecursiveTask.Эти задачи передаются в FJPool с использованием метода submit()
.Я хочу иметь общий обработчик исключений, подобный UncaughtExceptionHandler
, где, если Задача выдает непроверенное / неперехваченное исключение, я могу обработать исключение и повторно отправить задачу, если требуется.Обработка исключения также гарантирует, что поставленные в очередь задачи не будут отменены, если одна или несколько задач выдают исключение.
invokeAll()
метод возвращает набор ForkJoinTasks, но эти задачи находятся в рекурсивном блоке (каждая задача вызывает метод compute()
и может быть разделена далее [гипотетический сценарий])
class RecursiveActionTask extends RecursiveAction {
public void compute() {
if <task.size() <= ACCEPTABLE_SIZE) {
processTask() // this might throw an checked/unchecked exception
} else {
RecursiveActionTask[] splitTasks = splitTasks(tasks)
RecursiveActionTasks returnedTasks = invokeAll(splitTasks);
// the below code never executes as invokeAll submits the tasks to the pool
// and the flow never comes to the code below.
// I am looking for some handling like this
for (RecusiveActionTask task : returnedTasks) {
if (task.isDone()) {
task.getException() // handle this exception
}
}
}
}
}
Я заметил, что при сбое 3-4 задач весь блок отправки очереди отбрасывается.В настоящее время я поставил try/catch
вокруг ProcessTask, который лично мне не нравится.Я ищу более общие.
- Я также хочу знать обо всем списке задач, которые не удалось, чтобы я мог повторно отправить их
- Когда задачи выдают исключения, делаютпотоки вытесняются из пула (хотя мой анализ обнаружил, что они не [но не уверены])?
- Вызов метода
get()
в FutureTask с большей вероятностью поместит мой поток в последовательное состояние, поскольку он ожидает, пока задача не завершится. - Я хочу знать статус задания, только если оно не выполнено.Мне все равно, когда он завершится (очевидно, не хочет ждать час спустя)
Есть идеи, как обрабатывать исключения в приведенном выше сценарии?