Note that there are some explanatory texts on larger screens.

plurals
  1. PORetrieving a task instance scheduled with ScheduledExecutorService
    text
    copied!<p>I got a <code>ScheduledExecutorService</code> for task scheduling in a JEE environment. Some of those task are leaving resources opened when they are interrupted with <code>ScheduledExecutorService.shutdownNow()</code> (e.g. open files with a third-party lib like Lucene).</p> <p>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 (e.g wait(), sleep(), etc) or if doing some IO operation in a interruptible channel the <code>Thread.interrupt()</code> will make a <code>InterruptedException</code> rise. In both cases, the finally block must be executed. See: <a href="http://download.oracle.com/javase/1,5.0/docs/api/java/lang/Thread.html#interrupt%28%29" rel="nofollow">http://download.oracle.com/javase/1,5.0/docs/api/java/lang/Thread.html#interrupt%28%29</a>.</p> <p>Obviously, I already tried to release the resources with a very well implemented finally block in the Task class, but in some environments (e.g. CentOS) the finally block is not executed when the thread is interrupted. And then I found this very cool note in the official Java Documentation:</p> <blockquote> <p>Note: If the JVM exits while the try or catch code is being executed, then the finally block may not execute. 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.</p> </blockquote> <p>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. Can I retrieve those references to the task classes from the <code>ScheduledExecutorService</code>? Or do you have some cool idea to resolve my problem in a better way?</p> <p><strong>The first solution: Wrap it!</strong></p> <p>Create a Wrapper class for the <code>ScheduledExecutorService</code> and add a property like this:</p> <pre><code>private IdentityHashMap&lt;ScheduledFuture&lt;?&gt;, Runnable&gt; taskList; </code></pre> <p>With that we can access any Runnable object directly, or by the <code>ScheduledFuture</code> related to it. For the instantiation of the wrapper, I can get the <code>ScheduledExecutorService</code> from the <code>Executors.newScheduledThreadPool()</code> method and pass it to my wrapper.</p> <p><strong>Another Solution: Extend it!</strong></p> <p>Extend the <code>ScheduledThreadPoolExecutor</code>, add the IdentityHashMap property and overwrite all the method that schedules or cancels jobs to add/remove the reference from the Map.</p> <p><strong>The problem with both solutions?</strong></p> <p>If the caller of your wrapper or extended class receive a <code>SchedulerFuture&lt;?&gt;</code> object, cancel the job with the <code>SchedulerFuture&lt;?&gt;.cancel()</code> method is possible, bypassing your "capsule". With the wrapper you can avoid passing the <code>SchedulerFuture&lt;?&gt;</code> 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).</p> <p><strong>The elegant solution: Your own scheduler!</strong> Thanks to Kaj for pointing it ...</p> <ol> <li>Extend the <code>ScheduledThreadPoolExecutor</code> to overwrite the <code>decorateTask()</code> method </li> <li>Decorate the <code>Runnable</code> with one implementation of a <code>ScheduledFuture</code> interface</li> <li>Implement one custom <code>cancel()</code> method that actually cancels the thread but also manipulates the <code>Runnable</code> object to force the resource releasing.</li> </ol> <p>Check my blog <a href="http://java.ggarciao.com/2011/08/how-to-release-resources-from.html" rel="nofollow">post</a> for the details and code exemples!!!</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload