检索使用ScheduledExecutorService调度的任务实例



我在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 29 #中断% 28%。

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

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

所以,我需要的是对所有计划任务的引用,以便在task类中实现强制释放资源的一些公共方法。我可以从ScheduledExecutorService检索那些对任务类的引用吗?或者你有什么好主意能更好地解决我的问题?

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

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

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

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

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

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

两个解决方案的问题是什么?

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

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

  1. 扩展ScheduledThreadPoolExecutor覆盖decorateTask()方法
  2. 用a的一个实现装饰RunnableScheduledFuture界面
  3. 实现一个自定义的cancel()方法取消线程,但也操纵Runnable对象强制
查看我的博客文章的细节和代码示例!!

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

听起来像一个非常糟糕的VM在CentOS上的实现,如果它真的没有执行那些finally块。在任何其他VM实现中都没有听说过。

您可以做的一种选择,而不是引用所有的计划任务,是子类化ScheduledThreadPoolExecutor并覆盖decorateTask方法,以便它们用您的类装饰任务,然后拦截cancel调用。

相关内容

  • 没有找到相关文章

最新更新