检索使用ScheduledExecutorService计划的任务实例

时间:2011-07-29 10:23:04

标签: java concurrency lucene scheduled-tasks try-catch-finally

我在JEE环境中获得了ScheduledExecutorService任务调度。其中一些任务是在ScheduledExecutorService.shutdownNow()中断时打开资源(例如,使用像Lucene这样的第三方库打开文件)。

我知道一个线程可能无法自行停止执行:必须使用的方法来停止线程正在窃听中断标志并停止方法执行,如果线程是阻塞的(例如wait(),sleep())等等)或者如果在可中断通道中进行一些IO操作,Thread.interrupt()将会InterruptedException上升。在这两种情况下,必须执行finally块。 请参阅:http://download.oracle.com/javase/1,5.0/docs/api/java/lang/Thread.html#interrupt%28%29

显然,我已经尝试在Task类中使用一个非常好的finally块释放资源,但是在某些环境(例如CentOS)中,当线程被中断时不会执行finally块。然后我在官方Java文档中找到了这个非常酷的说明:

  

注意:如果在执行try或catch代码时JVM退出,   那么finally块可能不会执行。同样,如果线程   执行try或catch代码被中断或终止,最后   即使作为一个整体的应用程序,块也可能无法执行   继续进行。

所以,我需要的是对所有计划任务的引用,以便在Task类中实现一些强制释放资源的公共方法。我可以从ScheduledExecutorService检索对任务类的引用吗?或者你有一个很好的想法,以更好的方式解决我的问题?

第一个解决方案:包裹它!

ScheduledExecutorService创建一个Wrapper类,并添加如下属性:

private IdentityHashMap<ScheduledFuture<?>, Runnable> taskList;

有了它,我们可以直接访问任何Runnable对象,或者通过与它相关的ScheduledFuture访问。对于包装器的实例化,我可以从ScheduledExecutorService方法获取Executors.newScheduledThreadPool()并将其传递给我的包装器。

另一种解决方案:扩展它!

扩展ScheduledThreadPoolExecutor,添加IdentityHashMap属性并覆盖调度或取消作业的所有方法,以添加/删除Map中的引用。

这两个解决方案存在问题?

如果包装器或扩展类的调用者收到SchedulerFuture<?>对象,则可以使用SchedulerFuture<?>.cancel()方法取消作业,绕过“胶囊”。使用包装器可以避免将SchedulerFuture<?>引用传递给调用者,但是使用扩展类不能(如果在扩展类中创建自己的方法,则会得到与包装器相同的结果,但是一种非常令人困惑的方式)。

优雅的解决方案:您自己的调度程序!感谢Kaj指出它......

  1. 扩展ScheduledThreadPoolExecutor以覆盖。{ decorateTask()方法
  2. 使用a的一个实现来装饰Runnable ScheduledFuture界面
  3. 实际实现一个自定义cancel()方法 取消线程但也操纵Runnable对象强制 资源释放。
  4. 查看我的博客post了解详情和代码示例!!!

1 个答案:

答案 0 :(得分:0)

你在安排什么?这些任务是什么样的?我发现很难相信finally块没有被执行。我猜这是你已经安排的任务,但是没有开始执行那些泄漏资源(因为他们的finally块不会被执行)

如果真的没有执行那些最终的块,那么在CentOS上听起来就像是一个非常糟糕的虚拟机实现。在任何其他VM实现中都没有听说过。

您可以执行的一个选项(而不是引用所有计划任务)是子类ScheduledThreadPoolExecutor并覆盖decorateTask方法,以便它们用您的类装饰任务,然后拦截取消调用。