I’m building a buffer in Java that will collect write actions requested by many threads, and flush them as a group, say, once per second. I’d like to give it a method called waitForFlush that will block and thread that calls it until the next flush event completes. Meanwhile, a separate, standalone thread is flushing and sleeping in a loop. So I’m basically looking for a concurrency structure or pattern that will allow many threads to block at a particular point, and then release them all simultaneously, and I’m finding that none of Java’s builtin concurrency primitives are a really close match for this. The best I’ve come up with so far is wait/notifyAll, as follows:
public class Buffer {
private volatile long lastFlushTime = System.currentTimeMillis();
private final Object flushMonitor = new Object();
public void waitForFlush() {
long entryTime = System.currentTimeMillis();
synchronized(flushMonitor) {
while(lastFlushTime <= entryTime) {
flushMonitor.wait();
}
}
}
public void flush() {
// do flush stuff here
synchronized(flushMonitor) {
lastFlushTime = System.currentTimeMillis();
flushMonitor.notifyAll();
}
}
}
Although I think this would work fine in practice, the synchronization block in waitForNotify() still feels somewhat imperfect to me. Ideally, for this use case, you would be able to call wait() without synchronizing on the associated Object, and all of the blocked threads would be released at the precise same moment when notifyAll() is called, instead of having to exit the synchronized block one-by-one.
So, in general, is there a better way to block and simultaneously release a variable number of threads than I’ve outlined above (the Semaphore and CountDownLatch classes would only work for for a fixed number of threads, I think)?
Though a CountDownLatch would work for a one time case as Marko Topolnik and munyengm mention. It fails in a cyclic scenario (that is you can only
await&countDownonce per CDL). Then you may consider a CyclicBarrier, but that fails in your case because you would need to know the number of threads being used.If you can use Java 7 I recommend Phaser. You can have single thread signalling to many waiting threads and reuse.