Я использую службу ScheduledExecutorService, к которой я добавляю как входящие, так и запланированные Runnables (используя scheduleWithFixedDelay). Намерение состоит в том, чтобы иметь очень длинные процессы, и, следовательно, у меня не было определенных жизненных циклов. Я в основном хочу, чтобы основной поток реагировал только на исключения и прерывания. Плановые задачи являются критическими, например. генерируя тепловые биты, и, таким образом, если какая-либо нить бросает ошибку runtimeexception, я хочу зарегистрировать исключение, прервать все остальные потоки и закрыть программу.Обработка исключений с несколькими фьючерсами из ScheduledExecutorService
Как я должен обрабатывать исключения? Служба ScheduledExecutorService проглатывает все исключения, если я не запустил Future.get().
Цитирование через фьючерсы, как показано ниже, не работает. Если первый элемент в списке фьючерсов не возвращает никаких ошибок, которые блокируют поток от прослушивания других потоков, которые могут возвращать ошибку.
for (Future<?> future : futures) {
future.get();
}
Один из вариантов будет пробегаем по фьючерсам с просьбой, если они сделаны, как показано ниже, но мне не очень нравится это решение. Мне нужно добавить поток sleep и, таким образом, отклик на исключение задерживается.
boolean allActive = true;
while (allActive) {
for (Future<?> future : futures) {
if (!future.isDone()) {
allActive = false;
break;
}
}
Thread.sleep(50);
}
Какие еще варианты у меня есть? Или я неправильно подхожу к проблеме? Не следует ли вообще использовать ScheduledExecutorService и реализовать расписание самостоятельно в моем собственном потоке?
Пример кода, попробуйте изменить порядок в будущем списке! Я хочу, чтобы поведение, которое вы получите, если добавить ручку, прежде чем handle2 но порядок списка не имеет значения:
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class Test {
private static int i = 0;
public static void main(String[] args) throws Exception {
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
Future<?> handle = scheduler.scheduleWithFixedDelay(new Runnable() {
public void run() {
System.out.println("No exception!");
if (i > 2) {
System.out.println("Exception!");
throw new RuntimeException("foo");
}
i++;
}
}, 0, 500, TimeUnit.MILLISECONDS);
Future<?> handle2 = scheduler.scheduleWithFixedDelay(new Runnable() {
public void run() {
System.out.println("Running!");
}
}, 0, 500, TimeUnit.MILLISECONDS);
List<Future<?>> futures = new ArrayList<>();
futures.add(handle2);
futures.add(handle);
try {
for (Future<?> future : futures) {
future.get();
}
} catch (Exception e) {
scheduler.shutdownNow();
System.out.println(scheduler.awaitTermination(1, TimeUnit.SECONDS));
System.out.println("Shuwdown complete");
e.printStackTrace();
}
}
}
Для таких задач вам может понравиться ['ListenableFuture'] Guava (https://github.com/google/guava/wiki/ListenableFutureExplained). – dimo414
Вы думали использовать «isCancelled()»? – efekctive