繁体   English   中英

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

[英]Retrieving a task instance scheduled with ScheduledExecutorService

我有一个ScheduledExecutorService用于在JEE环境中进行任务调度。 其中一些任务在被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类中使用一个实施得很好的final块来释放资源,但是在某些环境(例如CentOS)中,当线程中断时,finally块不会执行。 然后我在官方Java文档中发现了这个非常酷的注释:

注意:如果在执行try或catch代码时JVM退出,则finally块可能不会执行。 同样,如果执行try或catch代码的线程被中断或杀死,即使整个应用程序继续运行,finally块也可能不会执行。

因此,我需要引用所有已调度的任务,以便在Task类中实现一些强制释放资源的公共方法。 我可以从ScheduledExecutorService检索对任务类的那些引用吗? 还是您有一些好主意,可以更好地解决我的问题?

第一个解决方案:把它包起来!

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

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

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

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

扩展ScheduledThreadPoolExecutor ,添加IdentityHashMap属性,并覆盖所有计划或取消作业的方法,以从地图添加/删除引用。

两种解决方案都存在问题?

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

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

  1. 扩展ScheduledThreadPoolExecutor以覆盖decorateTask()方法
  2. 使用ScheduledFuture接口的一种实现来装饰Runnable
  3. 实现一个自定义的cancel()方法,该方法实际上取消线程,但也操纵Runnable对象以强制释放资源。

检查我的博客文章的详细信息和代码示例!

您要安排什么时间? 任务是什么样的? 我发现很难相信未执行finally块。 我想这是您已计划的任务,但是尚未开始执行的任务正在泄漏资源(因为它们的finally块将不会执行)

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM