views:

73

answers:

3

Lets say I have a instance method named myMethod(). I need to check if any thread is executing the method. Is there a way I can check this using reflection or some other API?

I want to execute some cleanup logic when the method is NOT in execution. Hence need to check if the method is running or not.

+5  A: 

There is no way to do exactly what you said (check whether other threads are inside of a method directly).

However, this sounds like a classic case for synchronization. Make the method invocation synchronize on some object's monitor; make your cleanup code synchronize on the same monitor, and voila! Now, if any thread is running the method(s) that you've made synchronized, your cleanup code can't run, but will wait until all threads have exited the methods and will then proceed.

Here's an example:

public class Foo
{
    private final Object LOCK = new Object();

    public void importantMethodOne()
    {
        synchronized(LOCK)
        {
            // Method body here
        }
    }

    public void importantMethodTwo()
    {
        synchronized(LOCK)
        {
            // Method body here
        }
    }

    public void otherMethod()
    {
        // Method body here
    }

    public void cleanupMethod()
    {
        synchronized(LOCK)
        {
            // Method body here
        }
    }
}

The LOCK monitor is a mutex - only one thread can hold it at once, so only one thread can be calling any of importantMethodOne, importantMethodTwo or the cleanupMethod at once. Any threads that try to invoke any of these methods while another is within the scope (and thus has the lock) will wait. In this example, otherMethod can be called at any time without interrupting anything else, because it doesn't acquire the lock.

Note that in this case, two threads cannot execute myMethod() at once because they'll block each other. If this is an issue, you can get around this with a ReadWriteLock (which allows many "readers" to hold it at once but one "writer"). If you acquire the read lock for your "normal" methods and the write lock for your "cleanup" methods, this will have the desired semantics.

Andrzej Doyle
It is actually possible to check if any other thread is currently executing an arbitrary method. You can use the `ThreadMXBean` in the management API to get the stack traces for all active thread, iterate through these and check if you find the relevant method.
jarnbjo
Well, you could, but that depends on the JMX manager being enabled. You could also just get hold of `Thread` references directly and call `getStackTrace()` on those, matching on the StackTraceElements. Neither of these are remotely sensible suggestions; firstly because they are the equivalent of throwing a **lot** of exceptions in the happy-path case; and more importantly because there's still no synchronization. There's nothing to set that a test the *just* returned `true` will still be `true` when you fire off a method dependent on its result.
Andrzej Doyle
Actually my answer tells you how to do exactly what he asked. It doesn't answer the question he SHOULD HAVE asked, yours does.
Bill K
Very true, I'll give you that. :-)
Andrzej Doyle
A: 

can you elaborate it more with example, to clean up you can always use finally block, and otherwise set a static flag that will be set true on entance of a method and false of exit, run a task to check if flag is false perform your cleanup

org.life.java
and yes, make sure no thread enters when cleanup is going on
org.life.java
A: 

I suppose you could have something like this: (Use indentation, don't feel like dealing with braces today)

int busy;

public boolean is Running()
    synchronized(lock1)
        return busy != 0;

public void run()
    try {
        synchronized(lock1)
            busy++

        do lots of stuff here
    } finally {
        synchronized(lock1)
            busy--
    }

It's early, but my tired brain can't find a problem with this--I'll re-read it later and see if it still makes sense.

But you will need more synchronization logic to ensure that nothing enters it while you are cleaning up--I didn't code that since today I'm answering the question you asked and not the one you meant to ask (others already did that)

Bill K
What if "do lots of stuff here" throws an exception or if the cleanup thread checks isRunning, get a false result and some other thread invokes the run method before the cleanup operation is finished?
jarnbjo
@jambo Yeah, good point put the busy in a finally clause. I DID mention your second point exactly though. I'll fix your point.
Bill K