【问题标题】:Get Runnable objects I scheduled using ScheduledThreadPoolExecutor when using shutdownNow() method获取我在使用 shutdownNow() 方法时使用 ScheduledThreadPoolExecutor 安排的可运行对象
【发布时间】:2011-01-21 00:07:43
【问题描述】:

我正在使用 ScheduledThreadPoolExecutor.schedule(Runnable,int,TimeUnit) 来调度实现 Runnable 的类的一些对象。

在某个时间点,我的应用程序将关闭,我使用ScheduledThreadPoolExecutor.shutdownNow()。根据文档,它返回一个 ScheduledFuture 的列表。

我真正想做的是获取我最初计划的对象,并从中获取一些数据,然后我将输出它说它无法执行。稍后,应用程序将使用它来尝试在应用程序重新启动时执行它。

【问题讨论】:

  • 实际上,您指向的 javadoc 说它返回一个 Runnables 列表。你是这个意思吗?
  • 方法规范是List,但是shutdownNow()方法的实际文本说它是ScheduledFuture的。我猜这确实意味着 RunnableScheduledFuture,因为返回类型必须是 Runnable,但即使使用该接口,似乎也没有办法获取我计划的原始对象:(

标签: java multithreading threadpool executorservice


【解决方案1】:

获取有关提交给执行程序的对象的信息的常用方法是维护指向原始对象的指针(可以是 Callable、Runnable 等的扩展)。在您调用 shutdownNow() 并考虑到由 等待 执行的对象返回的 Runnable 之后,您可以使用它来修剪您的原始对象列表并询问实际运行的对象。

【讨论】:

  • 嗯...所以如果我要添加一个包含对 Runnable 的引用的 Map,我会使用 Future 对象安排,并在 run() 方法结束时将其从该 Map 中删除,那应该可以正常工作。因此,当我调用 shutdownNow() 时,我会遍历 Map 并查询 Future 以查看它是否完成。这听起来可行吗?还是我太复杂了?
  • 你应该小心这种方法的内存泄漏,我建议尽快从集合中删除。取决于您将在关机前提交多少任务。
  • 这可能是有道理的,尽管如果我将删除代码放在 run() 方法最后的 finally 块中,我可以安全地避免内存泄漏。
  • 如果您需要查询已运行的对象,在我看来您别无选择,只能保留指向它们的指针。
【解决方案2】:

如果您只想将信息呈现给用户,最简单的方法可能是为您正在安排的Runnables 实现一个有意义的toString() 方法。然后你可以简单地迭代Executor 给你的列表并记录你得到的东西。

但可悲的事实是,您的原始对象被 Executor 包裹。然后,您需要保留一份手动传递给Executor 的列表,并让Runnables 在执行时从该列表中删除自己。显然,您需要为此使用线程安全列表。

【讨论】:

  • 问题是我没有出现(虽然实际上没有运行代码)来获取我安排的原始 Runnable,所以我不能这样做。正如你和 Kelly Vista 所建议的,我需要保留一份清单。
  • 它们被包装在 FutureTask 中,FutureTask 将它们包装在 AbstractQueuedSynchronizer 中,后者将它们包装在 Callable 中。他们很难得到:)
  • 是的,做这样的事情很烦人。这让我有点困惑。当从shutdownNow() 传递一个列表时,希望能够获得您安排的原始对象不是很常见的事情吗?这就是我所期望的,这就是 ThreadPoolExecutor 似乎是这样做的。
猜你喜欢
  • 2021-07-02
  • 1970-01-01
  • 2018-01-08
  • 2015-02-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多