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
精彩评论