繁体   English   中英

为什么我的执行器服务线程挂在 java 中?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM