在Spring Web应用程序内部,我有一个计划的任务,每五分钟调用一次。

 @Scheduled(fixedDelay = 300000)
     public void importDataTask()
{
    importData(); //db calls, file manipulations, etc..
}


通常,该任务可以顺利运行几天,但是有时会发生示例方法importaData()不会终止的情况,因此不会再次调用importDataTask(),并且在我重新启动应用程序之前,所有操作都将被阻止。

问题是:是否有一种可行的方法来确保该方法不会被无限期地阻塞(正在等待资源或其他东西)?

最佳答案

问题是:是否有可行的方法来确保一种方法
  不会无限期地被阻止(正在等待资源,或者
  还有什么)?


如果无法以精确的规则间隔计划调度,则可能不应该使用固定的延迟,而应使用两个条件:延迟+最后执行完成。
您可以安排一个任务,检查是否满足两个条件,如果满足,则运行重要处理。否则,它将等待下一个计划。
这样,您不应被阻止。如果任务超过固定的延迟,您可以等待一段时间。如果由于经常超过固定延迟而出现问题,则可能不应该使用固定延迟,或者应明智地增加固定延迟,以使其不那么常见。

这是一个示例(不使用编辑器编写。抱歉,如果有任何错误):

private boolean isLastImportDataTaskFinished;

@Scheduled(fixedDelay = 300000)
 public void importDataTaskManager(){
    if (isLastImportDataTaskFinished()){
        new Thread(new ImportantDataProcessing())).start();
    }
    else{
        // log the problem if you want
    }
}

 private isLastImportDataTaskFinished(){
   // to retrieve this information, you can do as you want : use a variable
   //  in this class or a data in database,file...
   // here a simple implementation
   return isLastImportDataTaskFinished;
 }


可运行类:

 public class ImportantDataProcessing implements Runnable{
   public void run(){
      importData(); //db calls, file manipulations, etc..
  }
}




评论:


  但是,如果我将其作为线程运行,如果发现它超出了范围,该如何杀死它
  时间限制,因为我对此没有任何参考(以
  使用第二项任务确定卡住状态)?


您可以使用ExecutorService(您对此有疑问:How to timeout a thread)。

这是一个非常简单的示例:

ExecutorService executor = Executors.newSingleThreadExecutor();
Future future = executor.submit(new ImportantDataProcessing());
try {
    future.get(100, TimeUnit.SECONDS);
}
catch (InterruptedException e) {
    e.printStackTrace();
}
catch (ExecutionException e) {
    e.printStackTrace();
}
catch (TimeoutException e) {
    // the timeout to handle but other exceptions should be handled :)
    e.printStackTrace();
}
executor.shutdown();


如果ImportantDataProcessing处理可能返回有趣的信息,则可以使用任务而不是可运行实例来键入future。

10-07 16:35
查看更多