【问题标题】:ScheduledExecutorService only runs onceScheduledExecutorService 只运行一次
【发布时间】:2017-10-17 08:11:49
【问题描述】:

我希望在启动我的网络服务后运行一个进程,然后每隔 30 分钟左右运行一次,(我现在正在以较小的延迟对其进行测试,只是为了看看它是否有效),但我的进程从未运行不止一次。我做错了什么?

这是我的代码:

@WebListener
public class SchedulerService implements ServletContextListener{

    @Autowired
    UpdateSubscriberService updateSubscriberService;

    ScheduledExecutorService scheduledExecService;

    public SchedulerService(){
        scheduledExecService = Executors.newSingleThreadScheduledExecutor();
    }

    @Override
    public void contextDestroyed(ServletContextEvent arg0) {
        scheduledExecService.shutdown();
    }

    @Override
    public void contextInitialized(ServletContextEvent arg0) {
        scheduledExecService.scheduleWithFixedDelay(new Runnable(){
            @Override
            public void run() {
                Date date = new Date(System.currentTimeMillis());
                System.out.println("Running scheduled update check " + date.toString());
                updateSubscriberService.checkForUpdates();
            }
        }, 60, 30, TimeUnit.SECONDS);
    }
}

【问题讨论】:

  • 你确定 run() 方法会返回吗?

标签: java spring spring-mvc scheduled-tasks scheduler


【解决方案1】:

在类似的问题上看到这个更长的Answer

try catch 包裹run 代码

只是猜测:正在引发异常。如果遇到异常,ScheduledExecutorService 会静默停止,不再执行预定的工作。

run 方法的代码应始终由 try-catch 包围,以处理和吸收任何抛出的异常。

 @Override
 public void run() {
    try {  // Let no Exception reach the ScheduledExecutorService.
        Date date = new Date(System.currentTimeMillis());
        System.out.println("Running scheduled update check " + date.toString());
        updateSubscriberService.checkForUpdates();
    } catch ( Exception e ) {
        System.out.println( "ERROR - unexpected exception" );
    }
}

存根run方法

迈出小步。从 run 方法开始,该方法除了 System.out.println 之外什么都不做。

【讨论】:

  • 当我将其更改为仅打印语句时,它应该执行多次,所以至少我现在知道问题不在于调度代码!
  • 您好 Basil,如果我想使用 ScheduledExecutorService 只运行一次怎么办?为什么我要问这个,因为我有 2 个课程,其中一个课程必须安排,而另一个课程只能运行一次。
  • @mannedear 然后使用ScheduledExecutorService以外的其他执行器服务。研究Tutorial 并搜索 Stack Overflow 以了解更多信息。
  • @BasilBourque 我打算使用一个标志并调用ScheduledExecutorService 类取消方法。您对此有何看法?
  • @mannedear 你需要发布你自己的问题,并说明情况。
【解决方案2】:

以防万一您处于代码必须每隔很多秒运行一次的位置,即使最后一次运行尚未完成(如果管理不当,这可能非常危险),您可以启动您的进程在计时器内的不同线程中。这是示例代码。

ScheduledExecutorService scheduledExecService = newSingleThreadScheduledExecutor();
scheduledExecService.scheduleWithFixedDelay(new Runnable()
{
    @Override
    public void run()
    {
        // This should be in a try-catch because any error here
        // will stop the recurrence
        try
        {
            // The timer will only repeat if the last run is finished. So
            // we put each new process in a different thread than the timer
            // itself, so the last timer call "finishes" as soon as the process
            // leaves the timer's thread.
            Thread t = new Thread(new Runnable()
            {
                public void run()
                {
                    try
                    {
                        android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                        MyProcessThatShouldRunEverySoManySecondsNoMatterWhat();
                    }
                    catch (Exception erTimerThread)
                    {
                        Log.e("Error", erTimerThread.toString());
                    }
                }
            });
            t.setPriority(2);
            t.start();
        }
        catch (Exception erTimer)
        {
            Log.e("Error", erTimer.toString());
        }
    }
}, 0, 60, java.util.concurrent.TimeUnit.SECONDS);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-11-10
    • 1970-01-01
    • 1970-01-01
    • 2021-08-18
    • 1970-01-01
    • 2018-04-06
    • 1970-01-01
    • 2011-12-13
    相关资源
    最近更新 更多