[英]Why is my executor service thread hanging in java?
我有一个 class 包含一个预定的执行程序服务,每 5 秒运行一次任务。 有时,由于我已实现的重试逻辑,任务本身可能需要超过 5 秒的时间。 在这种情况下,我假设即使我有调度程序每 5 秒运行一次任务,它也只是等到重试完成。 但是,在 2 次失败尝试后,我看到了失败日志,并且不再看到每 5 秒拨打一次电话。
import io.dropwizard.lifecycle.Managed;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import net.jodah.failsafe.Failsafe;
import net.jodah.failsafe.RetryPolicy;
import org.skife.jdbi.v2.Handle;
import org.skife.jdbi.v2.IDBI;
@Slf4j
public class DBTask implements Managed
{
private final IDBI dbi;
private final String validationQuery;
private final ScheduledExecutorService runner;
private final RetryPolicy policy;
public DBHealthCheckTask(@NonNull final IDBI dbi, @NonNull final String validationQuery)
{
this.dbi = dbi;
this.validationQuery = validationQuery;
runner = Executors.newSingleThreadScheduledExecutor();
policy = new RetryPolicy()
.withDelay(5 , TimeUnit.SECONDS)
.withMaxRetries(2)
.retryOn(Exception.class);
}
@Override
public void start() throws Exception
{
int intervalSecs = 5;
runner.scheduleAtFixedRate(this::runWithRetry, intervalSecs, intervalSecs, TimeUnit.SECONDS);
}
@Override
public void stop()
{
runner.shutdown();
}
private void runWithRetry()
{
Failsafe.with(policy)
.onRetry(r -> log.info("Database connection failed.", r))
.onFailure(r -> log.warn("WARNING- Database is unhealthy.", r))
.run(this::run);
}
private void run()
{
try (Handle handle = dbi.open())
{
handle.execute(validationQuery);
}
}
}
一旦我看到“WARNING”日志,我希望该任务会再次继续,然后它会在我看到另一个“WARNING”日志之前延迟 5 秒再重试 2 次。 但我只看到一个日志,之后什么都没有发生。
方法runWithRetry
会在 2 次重试失败时抛出异常。 对于调度,如果在执行任务时发现异常,则不会设置下一个任务执行。 因此,如果我们希望任务始终被调度,则需要手动捕获任务异常。 在您的情况下,请执行以下操作:
private void runWithRetry()
{
try{
Failsafe.with(policy)
.onRetry(r -> log.info("Database connection failed.", r))
.onFailure(r -> log.warn("WARNING- Database is unhealthy.", r))
.run(this::run);
}catch(Exception e){
//handle exception, make sure no exception rethrow
}
}
WARNING- Database is unhealthy
,仅在最后一轮重试后打印,因此在run()
中添加一些日志,您将看到重试过程。
private void run() {
// add some log here
// System.out.println("hello");
try (Handle handle = dbi.open()) {
handle.execute(validationQuery);
}
}
JavaDoc的解释
policy fails.如果配置了多个策略,则在执行完成且策略失败时调用此处理程序。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.