This week's book giveaway is in the Mac OS forum.
We're giving away four copies of a choice of "Take Control of Upgrading to Yosemite" or "Take Control of Automating Your Mac" and have Joe Kissell on-line!
See this thread for details.
The moose likes Threads and Synchronization and the fly likes executing time-bounded job Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


JavaRanch » Java Forums » Java » Threads and Synchronization
Bookmark "executing time-bounded job" Watch "executing time-bounded job" New topic
Author

executing time-bounded job

Dan Murphy
Ranch Hand

Joined: Mar 29, 2005
Posts: 126
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 ]

SCJP, SCJD, SCWCD
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
ExecutorService has a shutdown() method that you should call in the finally block.


"I'm not back." - Bill Harding, Twister
Dan Murphy
Ranch Hand

Joined: Mar 29, 2005
Posts: 126
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
Sheriff

Joined: Jan 30, 2000
Posts: 18671
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

Joined: Mar 29, 2005
Posts: 126
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
Sheriff

Joined: Jan 30, 2000
Posts: 18671
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

Joined: Mar 29, 2005
Posts: 126
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
Sheriff

Joined: Jan 30, 2000
Posts: 18671
[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.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: executing time-bounded job