gpt4 book ai didi

java - 使用 ExecutorService 的时间限制任务

转载 作者:行者123 更新时间:2023-11-29 03:07:16 24 4
gpt4 key购买 nike

我已将长时间运行的任务提交给 ExecutorService。该任务可能会运行相当长的一段时间。同时,新的任务被提交到内部阻塞队列。

提交的任务完成后,会发回通知以从队列中释放任务以供执行。但是,有时,由于编程错误或网络问题,通知不会被触发。在这种情况下,我的任务队列可能会变得非常大,而且我可能会遇到任务可能永远位于队列中的情况。

为了克服这个问题,我正在考虑编写一个线程,它会定期检查队列中任务空闲的时间。如果任务在队列中等待了 15 分钟,我会假设较早提交的任务遇到错误,因此没有返回。然后我将从队列中逐出任务并允许它执行。

是否有任何现有机制来处理此问题,否则我将不得不编写此自定义逻辑?

注意:
我不喜欢 ScheduledExecutor 服务的原因是因为并非所有任务都需要定期执行。只有失败的场景应该在一定的延迟后执行。

编辑架构简要概述我正在设计的解决方案应该支持许多并发的静态文件下载。通常可能有数千个下载请求。下载请求由基于 UI 的应用程序触发。这样我就知道什么时候会触发请求。利用这种方法,我打算限制下载请求。

当用户创建一个请求(比如 300 个下载请求)时会发生什么?

  1. 应用程序工作线程创建 300 个下载任务
  2. 提交了 100 个任务。我定义了最大 HTTP 线程池大小,例如 100。这意味着我可以支持最多 100 个同步并行下载(servlet 2.5)任务反过来要求远程 HTTP 客户端执行 HTTP get .请注意,HTTP 线程尚未发挥作用
  3. 剩余 200 个请求正在排队。
  4. HTTP 客户端执行 HTTP Get。 HTTP 线程现在以阻塞方式流式传输响应。
  5. 收到 200 OK 后,我会创建一个通知,通知其中一个客户端已完成下载。
  6. 节流器现在将释放/提交先前排队的 200 个请求中的任务之一。

在我能够接收响应(HTTP 200/HTTP 500 等)的情况下,节流机制就像一个魅力。但是,例如,如果 servlet 本身抛出异常,我没有收到任何响应以指示 HTTP 工作线程空闲。因此任务有可能永远保留在队列中。为了克服这个问题,我在考虑一种基于计时器的方法,如果 15 分钟内没有 HTTP 响应,则提交下一个队列任务以供执行。一种避免重大内存泄漏的回退机制。

最佳答案

通过超时调用 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);
}

单独的线程池用于防止没有线程可用于监视,但线程可用于执行导致未监视任务的任务。

关于java - 使用 ExecutorService 的时间限制任务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31514914/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com