我将长期运行的任务提交给ExecutorService
。这项任务可能会持续一段时间。同时,新任务将提交到内部阻塞队列。
完成提交的任务后,将发回通知以从队列中释放任务以供执行。但是,有时,由于编程错误或网络问题,通知不会被触发。在这种情况下,我的任务队列可能会变得很大,我可能会遇到一个任务可能永远存在于队列中的情况。
为了解决这个问题,我正在考虑编写一个线程,该线程将定期检查任务在队列中处于空闲状态的时间。如果任务在队列中说15分钟,我将假设先前提交的任务遇到错误,因此没有返回。然后我将从队列中逐出任务并允许它被执行。
是否有任何现有的机制来处理这个问题,或者我必须编写这个自定义逻辑?
注意:
我不喜欢ScheduledExecutor
服务的原因是因为并非所有任务都要定期执行。只有在一定延迟后才能执行故障情形。
修改 架构简要概述 我正在设计的解决方案应支持许多并发静态文件下载。通常,可能有数千个下载请求。下载请求是从基于UI的应用程序触发的。这样我知道什么时候会触发请求。利用这种方法,我打算限制下载请求。
当用户创建300个下载请求的请求时会发生什么?
在我能够接收响应(HTTP 200 / HTTP 500等)的情况下,限制机制就像魅力一样。但是,例如,如果说servlet本身引发了异常,我就没有得到任何响应来指示HTTP工作线程是空闲的。因此,任务有可能永远保留在队列中。为了克服这个问题,我考虑了一种基于计时器的方法,如果15分钟内没有HTTP响应,则提交下一个队列任务以供执行。一种回退机制,以避免重大内存泄漏。
答案 0 :(得分:4)
通过超时调用get()
并抓住TimeoutException
来限制任务允许的最长时间,执行清理。
这是一个在等待时不会阻止主线程的实现:
ExecutorService executor = Executors.newCachedThreadPool();
ExecutorService monitor = Executors.newFixedThreadPool(99);
public void submit(Runnable task) {
Runnable monitorTask = new Runnable() {
@Override
public void run() {
Future<?> future = executor.submit(task);
try {
future.get(15, TimeUnit.MINUTES);
} catch (InterruptedException e) {
// retry waiting. iterative approach not shown here
} catch (ExecutionException e) {
// your task exploded
} catch (TimeoutException e) {
// your task timed out - perform clean up, eg
future.cancel(true);
}
}
};
monitor.submit(monitorTask);
}
单独的线程池用于防止没有可用于监视的线程,但是可用于执行导致不受监视任务的任务的线程。