У меня есть экземпляр ScheduledExecutorService
- размер пула потоков по некоторым бизнес-требованиям равен 1 - который через некоторое время начинает зависать. Задания все еще отправляются, пул потоков все еще «работает», однако задача никогда не выполняется.
Чтобы предотвратить вечный запуск потока, я включил тайм-аут, который выполняет задачу исключительно после заданного времени ожидания. ,Локально все работает нормально (включая тайм-ауты), но при развертывании на сервере через некоторое время он начинает зависать.
Я думаю, это вызвано некоторой блокировкой во время выполнения задачи, но я ожидал тайм-аутчтобы решить эту проблему (я что-то упустил?).
Метод, отвечающий за выполнение задач:
private synchronized <T> CompletableFuture<T> submit(Supplier<T> supplier, ScheduledExecutorService delegate) {
CompletableFuture<T> completableFuture = new CompletableFuture<>();
completableFuture.whenComplete((input, exception) -> {
if (completableFuture.isCompletedExceptionally()) {
log.error("Error executing", exception);
}
});
delegate.schedule(() -> {
Timeouter timeouter = new Timeouter(30, completableFuture);
completableFuture.complete(new Task<>(supplier).run(completableFuture, timeouter));
}, 10, TimeUnit.SECONDS);
return completableFuture;
}
И вспомогательные классы, отвечающие за тайм-аут:
public class Timeouter extends TimerTask {
private Timer timer = new Timer();
private int timeout;
private CompletableFuture<?> completableFuture;
Timeouter(int timeout, CompletableFuture<?> completableFuture) {
this.timeout = timeout;
this.completableFuture = completableFuture;
}
public void start() {
timer.schedule(this, Duration.ofSeconds(timeout).toMillis());
}
void stop() {
timer.cancel();
timer.purge();
}
@Override
public void run() {
completableFuture.completeExceptionally(
new TimeoutException(String.format("Job timed-out after %s seconds", timeout)));
}
}
public class Task<T> {
private Supplier<T> supplier;
public Task(Supplier<T> supplier) {
this.supplier = supplier;
}
public T run(CompletableFuture<T> completableFuture, Timeouter timeouter) {
timeouter.start();
try {
T response = supplier.get();
return response;
} catch (Throwable t) {
completableFuture.completeExceptionally(t);
return null;
} finally {
timeouter.stop();
}
}
}
Любая помощь будет оценена.