在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。