0

我有几个 Callables 查询一些 JMX Bean,所以每个都可能超时。我想轮询值让我们说每一秒。最天真的方法是在单独的线程中启动每个线程,但我想尽量减少线程数。我必须以更好的方式做哪些选择?

4

3 回答 3

1

我的解释是你有一堆 Callable 对象,需要在某个时间间隔进行轮询。如果你使用线程池,问题是池会被最慢的成员污染,而你更快的成员会被饿死。

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

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

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

于 2009-05-23T06:48:53.467 回答
0

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

于 2009-06-04T12:13:36.560 回答
0

只要您收到一个submit-未来结果的句柄。您可以决定在给定的时间内等待其完成:CallableFuture

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

使用超时调用 get 允许您在任务尚未完成时收到异常。这不区分未开始的任务和已开始但未完成的任务。另一方面,cancel将采用布尔参数mayStopIfRunning,因此您可以选择仅取消尚未安排的任务。

于 2009-06-03T22:02:55.617 回答