开发者

Is there an alternate/better way to do this simple logic in java?

I have a method, say method1(), that takes a while to run. During it's execution, if there is another call to method1(), it should be ignored. I have, roughly, something like this

    boolean mFlag = false;

    void method1()
    {
        if(!mFlag)
        {
           mFlag=true;

           // do Stuff

          mFlag=false;
        }
    }

This works. But I was wondering if there is a better way to do this preferably 开发者_开发知识库not involving any flags.


Yes, you should really be using something from java.util.concurrent.locks Your example isn't quite strictly correct, that boolean needs to be volatile.

ReentrantLock lock = new ReentrantLock();

    void method1()
    {
        if(lock.tryLock())
        {
           try {
             if (!(lock.getHoldCount() > 1)) {
               //do Some Stuff
             }
          } finally {
            lock.unlock();
          }
        }
    }

Edited to handle skipping execution on reentrance as inidicated in your comment. Unfortunatly there isn't really a great way to do that with the built in library, as it's a bit of an odd usecase, but I still think using the built in library is a better option.


Are you trying to guard against re-entry from the same thread or multiple threads accessing at the same time.

Assuming multi-threaded access, the light approach is to use java.util.concurrent.atomic. No need for anything as "heavy" as a lock (provided there are not further requirements).

Assuming no-reentry from the same method:

private final AtomicBoolean inMethod = new AtomicBoolean();

void method1() {
    if (inMethod.compareAndSet(true, false)) { // Alternatively getAndSet
        try {
            // do Stuff
        } finally {
            inMethod.set(false); // Need to cover exception case!
        }
    }
}

If you want to allow reentry within the same thread, then it gets messy enough to use locks:

private final AtomicReference<Thread> inMethod = new AtomicReference<Thread>();

void method1() {
    final Thread current = Thread.currentThread();
    final Thread old = inMethod.get();
    if (
        old == current || // We already have it.
        inMethod.compareAndSet(null, current) // Acquired it.
    ) {
        try {
            // do Stuff
        } finally {
            inMethod.set(old); // Could optimise for no change.
        }
    }
}

Could use the Execute Around idiom for this.


Maybe you should use synchronized methods

http://download.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜