停止Spring计划执行,如果它在一段固定时间后挂起 [英] stop Spring Scheduled execution if it hangs after some fixed time

查看:228
本文介绍了停止Spring计划执行,如果它在一段固定时间后挂起的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用Spring Framework的 Scheduled 来安排我的作业每隔5分钟使用cron运行一次。但有时我的工作无限期地等待外部资源,我不能把超时放在那里。我不能使用 fixedDelay ,因为之前的进程有时会进入等待无限模式,我必须每隔5分钟刷新数据。

I have used Spring Framework's Scheduled to schedule my job to run at every 5 mins using cron. But sometime my job waits infinitely for an external resource and I can't put timeout there. I can't use fixedDelay as previous process sometime goes in wait infinitely mode and I have to refresh data at every 5 mins.

所以我在Spring Framework的 Scheduled 中寻找任何选项来在固定时间运行成功与否。

So I was looking any option in Spring Framework's Scheduled to stop that process/thread after a fixed-time either it run successfully or not.

我发现下面的设置初始化 ThreadPoolExecutor ,120秒 keepAliveTime 我放入 @Configuration 类。任何人都可以告诉我这将按预期工作。

I have found below setting which initialized ThreadPoolExecutor with 120 seconds for keepAliveTime which I put in @Configuration class. Can anybody tell me will this work as I expected.

@Bean(destroyMethod="shutdown")
public Executor taskExecutor() {
    int coreThreads = 8;
    int maxThreads = 20;
    final ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
            coreThreads, maxThreads, 120L, 
            TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>()
    );
    threadPoolExecutor.allowCoreThreadTimeOut(true);

    return threadPoolExecutor;
}


推荐答案

我不确定这个将按预期工作。确实keepAlive用于IDLE线程,我不知道你的线程在等待资源是否处于IDLE状态。此外,只有当线程数大于核心时,才会知道它何时发生,除非你监视线程池。

I'm not sure this will work as expected. Indeed the keepAlive is for IDLE thread and I don't know if your thread waiting for resources is in IDLE. Furthermore it's only when the number of threads is greater than the core so you can't really know when it happen unless you monitor the threadpool.


keepAliveTime - 当线程数大于核心时,这是多余空闲线程在终止之前等待新任务的最长时间。

keepAliveTime - when the number of threads is greater than the core, this is the maximum time that excess idle threads will wait for new tasks before terminating.

您可以做的是:

public class MyTask {

    private final long timeout;

    public MyTask(long timeout) {
        this.timeout = timeout;
    }

    @Scheduled(cron = "")
    public void cronTask() {
        Future<Object> result = doSomething();
        result.get(timeout, TimeUnit.MILLISECONDS);
    }

    @Async
    Future<Object> doSomething() {
        //what i should do
        //get ressources etc...
    }
}

不要忘记添加@EnableAsync

Don't forget to add @EnableAsync

通过实施,没有@Async也可以这样做a Callable。

It's also possible to do the same without @Async by implementing a Callable.

编辑:请记住,它会等到超时,但运行任务的线程不会被中断。发生TimeoutException时,您需要调用Future.cancel。并在任务检查isInterrupted()以停止处理。如果你正在调用api,请确保选中isInterrupted()。

Keep in mind that it will wait until timeout but the thread running the task won't be interrupted. You will need to call Future.cancel when TimeoutException occurs. And in the task check for isInterrupted() to stop the processing. If you are calling an api be sure that isInterrupted() is checked.

这篇关于停止Spring计划执行,如果它在一段固定时间后挂起的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆