安排在轮询情况下可能超时的可调用对象的最佳方法是什么?

发布于 2024-07-20 05:35:27 字数 133 浏览 7 评论 0原文

我有几个 Callables 查询一些 JMX Bean,因此每个 Callables 都可能会超时。 我想每秒轮询一次值。 最幼稚的方法是在单独的线程中启动每个线程,但我想最大限度地减少线程数量。 我必须采取哪些选择才能以更好的方式做到这一点?

I have several Callables which query for some JMX Beans, so each one may time out. I want to poll for values lets say every second. The most naive approach would be to start each in a separate thread, but I want to minimize the number of threads. Which options do I have to do it in a better way?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

别把无礼当个性 2024-07-27 05:35:27

我的解释是,您有一堆 Callable 对象,需要以一定的时间间隔进行轮询。 如果您使用线程池,问题在于该池将被最慢的成员污染,而较快的成员将挨饿。

听起来您可以控制调度,因此您可以考虑指数退避方法。 也就是说,在 Callable X 运行(并且可能超时)后,您需要等待 2 秒而不是 1 秒才重新安排它。 如果仍然失败,请转到 4 秒,然后是 8 秒,依此类推。如果您使用 ScheduledThreadPoolExecutor,它提供了一种内置方法来执行此操作,允许您在设定的延迟后安排执行。

如果您设置恒定的超时,此策略将降低您的池被慢速池垄断的可能性。 完全摆脱这个问题是非常困难的。 每个查询对象使用单独的线程实际上是确保您不会饥饿的唯一方法,正如您所说,这可能非常消耗资源。

另一种策略是将池分为快池和慢池。 如果一个对象超时(比如超过 N 次),则将其移至慢速池。 这可以让你的快速池保持快速,虽然慢速池会互相妨碍,但至少它们不会堵塞快速池。 如果他们在一段时间内有良好的统计数据,你可以将他们再次提升到快池中。

My interpretation is that you have a bunch of Callable objects which need to be polled at some interval. The trouble if you use a thread pool is that the pool will become contaminated with the slowest members, and your faster ones will be starved.

It sounds like you have control over the scheduling, so you might consider an exponential backoff approach. That is, after Callable X has run (and perhaps timed out), you wait 2 seconds instead of 1 second before rescheduling it. If it still fails, go to 4s, then 8s, etc. If you use a ScheduledThreadPoolExecutor, it comes with a built-in way to do this, allowing you to schedule your executions after a set delay.

If you set a constant timeout, this strategy will reduce your pool's susceptibility to monopolization by the slow ones. It is very difficult to get rid of this problem completely. Using a separate thread per queried object is really the only way to make sure you don't get starvation, and that can be very resource-intensive, as you say.

Another strategy is to bucket your pool into a fast one and a slow one. If an object is timing out (say more than N times), you move it to the slow pool. This keeps your fast pool fast, and while the slow ones all get in each others' way, at least they don't clog up the fast pool. If they have good statistics for a while, you can promote them to the fast pool again.

岁吢 2024-07-27 05:35:27

一旦您提交一个Callable,您就会收到一个Future - 未来结果的句柄。 您可以决定在给定的时间内等待其完成:

Future<String> future = executorService.submit(callable);
try {
  future.get(1, TimeUnit.SECONDS);
} catch ( TimeoutException e ) {
  future.cancel(true);
} catch ...

调用带有超时的 get 可以让您在任务尚未完成时收到异常。 这不区分未启动的任务和已启动但未完成的任务。 另一方面,cancel 将采用布尔参数 mayStopIfRunning,因此您可以选择仅取消尚未计划的任务。

As soon as you submit a Callable you receive a Future - a handle to the future result. You can decide to wait for its completion for a given amount of time:

Future<String> future = executorService.submit(callable);
try {
  future.get(1, TimeUnit.SECONDS);
} catch ( TimeoutException e ) {
  future.cancel(true);
} catch ...

Calling get with a timeout allows you to receive an exception if the task has not been completed. This does not distinguish between not started tasks and started but not completed. On the other hand cancel will take a boolean parameter mayStopIfRunning so you can choose to e.g. only cancel tasks not yet scheduled.

給妳壹絲溫柔 2024-07-27 05:35:27

我同意 robbotic...实现“cachedThreadPool”将解决您的问题,因为它将线程数量限制在最佳水平,同时超时,这将释放您未使用的资源

i agree with robbotic...implementing a 'cachedThreadPool' will solve your problem as it will restrict the number of threads to the optimum level at the same time has timeouts which will free your un-utilized resources

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文