Consider using an implementation of ExecutorService. Add tasks using the submit() methods, then tell the service not to accept more tasks with the shutdown() method -- tasks that have already been accepted will complete normally.
Looks like a task for ReentrantReadWriteLock
. Something like this:
class A {
private final ReadWriteLock lock = new ReentrantReadWriteLock();
public void x() {
if (!lock.readLock().tryLock()) throw new RuntimeException();
try {
...
} finally {
lock.readLock().unlock();
}
}
public void y() {
lock.writeLock().lock();
try {
...
} finally {
lock.writeLock().unlock();
}
}
}
Ok, how about using an ActiveObject
?
class X {
private static final ExecutorService service = Executors.newCachedThreadPool();
public void x(){
//Using anonymous class for brevity. Normal Runnable is ok. May be static inner class.
service.submit(new Runnable(){
@Override
public void run(){
//do stuff
}
});
}
//Derived from Java6 ExecutorService API
public void shutDownAndAwait(){
service.shutdownNow();
try{
if (!service.awaitTermination(60, TimeUnit.SECONDS))
throw new TerminationException("Service did not terminate");
}
} catch (InterruptedException ie) {
// (Re-)Cancel if current thread also interrupted
service.shutdownNow();
// Preserve interrupt status
Thread.currentThread().interrupt();
}
}//shutdownAndAwait
}//X
class Y {
private final X x = //inject reference
public void y(){
x.shutdownAndAwait();
}
}
The problem is that now execution of x() is asynchronous, so the original thread that called the x() are not sure when it was completed. And they are not interrupted when y() is called...
Java 7 is comming out with a new concurrency construct class, java.util.concurrent.Phaser. The phaser is a glorified cylcic barrier that allows awaiting on specific phases (or iterations) of a concurrent execution. You can download the latest binary jar at JSR 166's Interest Site.
My thought here is you have a volatile boolean yHasEnetered flag that initializes default to false. So in your X execution you could do :
if(yHasEnetered)
throw new IllegalStateException();
phaser.register();
//do work here
phasre.arrive();
The phaser itself will keep a running count of all registered parties so that when Y thread has entered, it can set the flag accordingly, register itself and await advance.
yHasEntered=true;
int phase = phaser.register();
phaser.arriveAndAwaitAdvance(phase);
//do y work here
yHasEntered=false;
At this point for Y thread. It will register itself get the phase that the phaser is currently on, arrive and wait for all other threads executing to reach their respective arrive block.