• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

executing time-bounded job

 
Ranch Hand
Posts: 126
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi,

I need to submit a job in it's own thread, but cancel the job (and kill the thread) if the job takes more than 5000ms to complete. I'm attempting to achieve this by using the facilities in java.util.concurrent like this:


However, it seems that the threads which are created to submit these jobs are not being killed. Initially, I thought this was happening because I only call future.cancel() when a TimeoutException is thrown and considered moving this call to the finally block instead. But according to the API docs, this method will fail if the job has already completed.

My guess is that the cancel() method only cancels the execution of the job, and never kills the thread that is used to execute the job. If this is correct, then presumably I need to add some code to the finally block that kills the thread whether the job has completed successfully or not, BUT I need to be sure that this won't happen until the timeout of 5000 has expired.

Thanks in Advance,
Dan

[ January 14, 2008: Message edited by: Dan Murphy ]
[ January 14, 2008: Message edited by: Dan Murphy ]
 
Wanderer
Posts: 18671
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
ExecutorService has a shutdown() method that you should call in the finally block.
 
Dan Murphy
Ranch Hand
Posts: 126
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks for the reply. The code I showed shown in my post is slightly different from the real code insofar as I don't actually create a new ExecutorService each time the method is called. Instead I reuse an ExecutorService that is a field of the class which contains submitJob().

If I were to call shutdown() in the finally block, then presumably I'd need to create a new ExecutorService each time the method is called, which I'd rather avoid for the sake of performance.

Is there a way that I can kill the threads without needing to create a new ExecutorService each time the method is called?
 
Jim Yingst
Wanderer
Posts: 18671
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Well, I'm not sure but I suspect that creating a new Thread may well be the most heavyweight part of creating a new ExecutorService. So I'm not sure it makes a lot of sense to reuse the ExecutorService but keep creating new Threads within it, if performance of that part of the code is an issue. I think it may well make more sense to just keep a certain number of threads in a pool more or less permanently, so they're always available when you need them. You can limit the maximum size of the pool, so you won't just keep adding threads, but instead keep reusing the one (or however many threads you put in the pool).

However if that doesn't work for you for some reason, you can do something like this:

By setting the core pool size to 0 and the max size to 1, the executor should have 0 or 1 thread at all times. Anytime there's no current task and nothing else in the queue, it should terminate the one thread and go back down to 0. Then when a new task arrives, it will create a new thread as necessary. However if it finishes one task and there's already another task in the queue, it will not end the current thread and create a new one. Instead it will just reuse the thread it has. Which seems more efficient anyway, after all.

You can also experiment with other values for core and max size, as well as for keep-alive time. You may find that you get better performance by having a slightly larger pool, or by allowing some keep-alive time so that threads don't get killed quite so quickly when they're idle. Or maybe you'll find that your performance isn't really impacted either way, which is entirely possible. It's easy to spend too much time optimizing things that turn out not to matter.
 
Dan Murphy
Ranch Hand
Posts: 126
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks again for the reply - very helpful. Your comments about creating a new thread for each job got me thinking about how to improve the efficiency of this code, and I'm considering the following:



Am I right in saying that by using a cached thread pool I don't need to worry about killing threads that are used to run submitted jobs? I'm presuming that the ExecutorService will take care of disposing of threads that are idle for longer than a specific period (60 seconds by default).

Of course, I should still call ExecutorService.shutdown() when I'm finished submitting jobs, which in this case will be when the web application shuts down - presumably a servlet context listener is the best place to do this sort of cleanup operation?

Thanks Again,
DM
[ January 14, 2008: Message edited by: Dan Murphy ]
 
Jim Yingst
Wanderer
Posts: 18671
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Yes, that all sounds correct and good. In all likelihood it will be best to just let the ExecutorService take care of disposing of inactive threads; they probaly don't need to be terminated right away as long as they don't linger forever. And calling shutdown from a servlet context listener sounds good, yes.
 
Dan Murphy
Ranch Hand
Posts: 126
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
So, to summarise....

1. Future.cancel() doesn't actually kill any threads, it just cancels a job that's currently executing

2. The only cleanup you need to do is ExecutorService.shutdown()

Is that correct?

Thanks Again,
Dan
 
Jim Yingst
Wanderer
Posts: 18671
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
[Dan]: 1. Future.cancel() doesn't actually kill any threads, it just cancels a job that's currently executing

Yes, or a job that's scheduled to execute but hasn't started yet. Whether or not it will cancel a currently-executing task will depend on whether the task has been written to respond well to an interrupt. Some tasks just naturally do that, while others may require you to insert periodic checks to Thread.currentThread().interrupted() to see if a cancel signal has been sent.

[Dan]: 2. The only cleanup you need to do is ExecutorService.shutdown()

Yes - at least that's the only cleanup for the executor. There may be other things going on in the program, of course.
 
Hey, sticks and stones baby. And maybe a wee mention of my stuff:
a bit of art, as a gift, the permaculture playing cards
https://gardener-gift.com
reply
    Bookmark Topic Watch Topic
  • New Topic