views:

405

answers:

8

I am writing a java program which tracks as threads are created in a program and is then supposed to perform some work as each Thread terminates.

I dont see any 'thread termination hooks' out there in the javadoc.

Currently the only way I can think of to achieve my requirement is to hold on to the thread objects and query its 'state' at repeated intervals.

Is there any better way to do this?

Edit: I cannot wrap the runnable or modify the runnable in any way. My code uses runtime instrumentation and just detects that a thread is created and gets a reference to the Thread object. The runnable is already running at this point.

+1  A: 

You could write a decorator for Runnable which calls a termination hook and wrap your thread code in it when you create the threads.

starblue
cant modify the runnable.edited the question to clarify this.
pdeva
I think the idea behind a decorator is that you wouldn't modify the Runnable, but rather do something like wrap it in another object. If you're saying you can't modify the already running thread, that's different.
TREE
+6  A: 

You can use the join() method.

EDIT

If your main thread must not be blocked until threads are not terminated, you can create a sub main thread which will call the threads, then wait for them with join() method.

Jérôme
That would mean i would need to create another thread 'b' for every thread 'a' i track so that 'b' could wait for 'a' to join.
pdeva
If your main thread is non blocking, that is the idea.
Jérôme
Seems like the best answer. Unless you are running a LOT of threads, it shouldn't matter--I've run quite a few and until you are in the thousands, don't stress too much. Waiting threads don't drain CPU.
Bill K
+1  A: 

If you added a try/finally block to each run method, the code inside would be executed when each thread completed. Let the thread be responsible for its own clean-up.

duffymo
cant modify the runnable.edited the question to clarify this.
pdeva
+2  A: 

I see four possible methods.

  1. Use your own Thread subclass with an overridden run() method. Add a finally block for thread termination.
  2. Use a Runnable with similar decoration, perhaps as a wrapper around the supplied Runnable. A variant of this is to subclass Thread in order to apply this wrapper at construction time.
  3. Create a 2nd thread to join() on the real thread and thus detect its termination.
  4. Use instrumentation to rewrite the Thread.run() method as above.
Darron
cant modify the Thread object or the runnable.using join would require one additional thread for every thread i track
pdeva
I'm adding a 4th method.
Darron
A: 

As you say, there are no thread termination hooks. You have to code them yourself; call some method on a controller at the end of the run() method of your Runnables (AFAIK subclassing Thread is considered bad practice, you should implement Runnable and create a Thread with that Runnable as its target).

You can also implement an UncaughtExceptionHandler to know if a thread terminated abnormally due to an exception, in which case your controller's method won't be called.

Chochos
+1  A: 

AspectJ could help you do this if you needed to inject code into third-party compiled code, but apparently it doesn't work on standard Java class libraries.

Looks like there's a whitepaper on doing this here, but there's no telling if it's practical. I think you have to pay for it.

http://portal.acm.org/citation.cfm?doid=1411732.1411754

You could download OpenJDK, put the hook in yourself, compile a custom JRE and ship that with your application :)

sjbotha
A: 

If you run on java 1.5 you can probably do it using java.lang.instrument and the -javaagent option to the jvm.

Redefine the run method on the thread object which should call your code. You already seem to use instrumentation so it should be available. as it modifies runtime bytecode you should be fine

That said, it is hard to provide a more specific and detailed answer your question lacks at least the jvm version and the main frameworks in use (think spring-aop, jboss-aop, jvm version etc)

Jean
+2  A: 

Just poking around in the (sun 1.5) source code for java.lang.Thread and sun.misc.VM, there is a field in thread called threadStatus. It is a private int and its values map to the enum java.lang.Thread.State. I have not verified this, nor determined how quickly it occurs if it does, but when a thread eventually terminates, this value will be set to java.lang.Thread.State.TERMINATED.

With this relatively simple condition to detect, I think it would be fairly straightforward to inject a field interceptor on threadStatus to fire an event when the field is set to a specific target value.

Nicholas
thats a pretty nice idea
pdeva