简体   繁体   English

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

[英]Retrieving a task instance scheduled with ScheduledExecutorService

I got a ScheduledExecutorService for task scheduling in a JEE environment. 我有一个ScheduledExecutorService用于在JEE环境中进行任务调度。 Some of those task are leaving resources opened when they are interrupted with ScheduledExecutorService.shutdownNow() (eg open files with a third-party lib like Lucene). 其中一些任务在被ScheduledExecutorService.shutdownNow()中断时使资源处于打开状态(例如,使用第三方库(如Lucene)打开文件)。

I know that a thread may not stop his execution by itself: The must used way to stop a thread is cheeking the interrupt flag and stopping the method execution, and if the thread is block (eg wait(), sleep(), etc) or if doing some IO operation in a interruptible channel the Thread.interrupt() will make a InterruptedException rise. 我知道一个线程可能不会自己停止执行:停止线程的必须使用的方法是检查中断标志并停止方法的执行,以及线程是否处于阻塞状态(例如,wait(),sleep()等)。或者,如果在可中断的通道中执行某些IO操作,则Thread.interrupt()将引发InterruptedException In both cases, the finally block must be executed. 在这两种情况下,必须执行finally块。 See: http://download.oracle.com/javase/1,5.0/docs/api/java/lang/Thread.html#interrupt%28%29 . 请参阅: http : //download.oracle.com/javase/1,5.0/docs/api/java/lang/Thread.html#interrupt%28%29

Obviously, I already tried to release the resources with a very well implemented finally block in the Task class, but in some environments (eg CentOS) the finally block is not executed when the thread is interrupted. 显然,我已经尝试在Task类中使用一个实施得很好的final块来释放资源,但是在某些环境(例如CentOS)中,当线程中断时,finally块不会执行。 And then I found this very cool note in the official Java Documentation: 然后我在官方Java文档中发现了这个非常酷的注释:

Note: If the JVM exits while the try or catch code is being executed, then the finally block may not execute. 注意:如果在执行try或catch代码时JVM退出,则finally块可能不会执行。 Likewise, if the thread executing the try or catch code is interrupted or killed, the finally block may not execute even though the application as a whole continues. 同样,如果执行try或catch代码的线程被中断或杀死,即使整个应用程序继续运行,finally块也可能不会执行。

So, what I need is a reference to all the scheduled task in order to implement some public method in the Task classes that force the release of resources. 因此,我需要引用所有已调度的任务,以便在Task类中实现一些强制释放资源的公共方法。 Can I retrieve those references to the task classes from the ScheduledExecutorService ? 我可以从ScheduledExecutorService检索对任务类的那些引用吗? Or do you have some cool idea to resolve my problem in a better way? 还是您有一些好主意,可以更好地解决我的问题?

The first solution: Wrap it! 第一个解决方案:把它包起来!

Create a Wrapper class for the ScheduledExecutorService and add a property like this: ScheduledExecutorService创建Wrapper类,并添加如下属性:

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

With that we can access any Runnable object directly, or by the ScheduledFuture related to it. 这样,我们可以直接访问任何Runnable对象,也可以通过与其相关的ScheduledFuture访问它。 For the instantiation of the wrapper, I can get the ScheduledExecutorService from the Executors.newScheduledThreadPool() method and pass it to my wrapper. 对于包装器的实例化,我可以从Executors.newScheduledThreadPool()方法获取ScheduledExecutorService并将其传递给我的包装器。

Another Solution: Extend it! 另一个解决方案:扩展它!

Extend the ScheduledThreadPoolExecutor , add the IdentityHashMap property and overwrite all the method that schedules or cancels jobs to add/remove the reference from the Map. 扩展ScheduledThreadPoolExecutor ,添加IdentityHashMap属性,并覆盖所有计划或取消作业的方法,以从地图添加/删除引用。

The problem with both solutions? 两种解决方案都存在问题?

If the caller of your wrapper or extended class receive a SchedulerFuture<?> object, cancel the job with the SchedulerFuture<?>.cancel() method is possible, bypassing your "capsule". 如果包装器或扩展类的调用者收到SchedulerFuture<?>对象,则可以使用SchedulerFuture<?>.cancel()方法取消作业,从而绕过“胶囊”。 With the wrapper you can avoid passing the SchedulerFuture<?> reference to the caller, but with the extended class you can't (if you create your own methods in the extended class you will get the same result as the wrapper, but in a very confusing way). 使用包装程序,您可以避免将SchedulerFuture<?>引用传递给调用方,但是使用扩展类则不能(如果在扩展类中创建自己的方法,则将获得与包装程序相同的结果,但是在非常令人困惑的方式)。

The elegant solution: Your own scheduler! 优雅的解决方案:您自己的调度程序! Thanks to Kaj for pointing it ... 感谢Kaj指出...

  1. Extend the ScheduledThreadPoolExecutor to overwrite the decorateTask() method 扩展ScheduledThreadPoolExecutor以覆盖decorateTask()方法
  2. Decorate the Runnable with one implementation of a ScheduledFuture interface 使用ScheduledFuture接口的一种实现来装饰Runnable
  3. Implement one custom cancel() method that actually cancels the thread but also manipulates the Runnable object to force the resource releasing. 实现一个自定义的cancel()方法,该方法实际上取消线程,但也操纵Runnable对象以强制释放资源。

Check my blog post for the details and code exemples!!! 检查我的博客文章的详细信息和代码示例!

What are you scheduling? 您要安排什么时间? What does the tasks look like? 任务是什么样的? I find it very hard to believe that the finally block isn't executed. 我发现很难相信未执行finally块。 I would guess that it's the tasks that you have scheduled, but that haven't started executing that are leaking resources (since their finally block won't be executed) 我想这是您已计划的任务,但是尚未开始执行的任务正在泄漏资源(因为它们的finally块将不会执行)

Sounds like a really bad VM implementation on the CentOS if it really aren't executing those finally blocks. 如果CentOS上没有真正执行这些finally块,这听起来像是一个糟糕的VM实现。 Haven't heard about that in any other VM implementation. 在其他任何VM实施中都没有听说过。

One option that you can do, instead of referencing all of the scheduled tasks, is to subclass ScheduledThreadPoolExecutor and override the decorateTask methods so that they decorate the tasks with your classes, and then intercept the cancel invokation. 您可以执行一个选择,而不是引用所有计划的任务,是对ScheduledThreadPoolExecutor进行子类化,并覆盖decorateTask方法,以便它们使用您的类来装饰任务,然后拦截取消调用。

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

相关问题 重新启动ScheduledExecutorService计划任务的正确方法是什么? - What is the correct way to restart a ScheduledExecutorService scheduled task? 取消在ScheduledExecutorService中计划的任务可使执行器保持活动状态 - Cancelling a task scheduled in a ScheduledExecutorService keeps executor alive ScheduledExecutorService - 检查计划任务是否已完成 - ScheduledExecutorService - Check if scheduled task has already been completed 如何使ScheduledExecutorService在其计划任务被取消时自动终止 - How to make a ScheduledExecutorService terminate automatically when its scheduled task is cancelled 使用ScheduledExecutorService时在何处执行计划任务的最终清理 - Where to perform final cleanup for a scheduled task when using a ScheduledExecutorService 停止预定的 ScheduledExecutorService - Stop a scheduled ScheduledExecutorService ScheduledExecutorService和计划的行为 - ScheduledExecutorService and scheduled behavior 如何强制执行Singleton(一个ScheduledExecutorService的全局实例),一次执行一项任务? - How to enforce singleton (one global instance of) ScheduledExecutorService, one task at a time? @Scheduled 和 scheduleExecutorService.scheduleWithFixedRate 在 java - @Scheduled and scheduledExecutorService.scheduleWithFixedRate in java ScheduledExecutorService等待任务完成 - ScheduledExecutorService wait for task to complete
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM