安排Callables的最佳方法是什么,可能会在投票情况下超时?

时间:2009-05-21 19:34:41

标签: java multithreading polling

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

3 个答案:

答案 0 :(得分:1)

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

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

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

另一个策略是将您的游泳池分为快速游戏和慢速游戏。如果某个对象超时(例如超过N次),则将其移至慢速池。这可以让您的快速游泳池保持快速,而慢速游泳池则可以保持快速游泳池的速度,至少它们不会堵塞快速游泳池。如果他们有一段时间的良好统计数据,您可以再次将它们提升到快速池。

答案 1 :(得分:0)

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

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

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

答案 2 :(得分:0)

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