You can use java.util.concurrent.locks.Condition
Java docs to pause for a while based on same condition.
This is approach looks clean to me and ReentrantLock mechanism has better throughput than synchronized. Read below excerpt from IBM article
As a bonus, the implementation of ReentrantLock is far more scalable
under contention than the current implementation of synchronized. (It
is likely that there will be improvements to the contended performance
of synchronized in a future version of the JVM.) This means that when
many threads are all contending for the same lock, the total
throughput is generally going to be better with ReentrantLock than
with synchronized.
BlockingQueue are best known for solution of producer-consumer problem, and it also uses Condition
for waiting.
See below example taken from Java doc's Condition, which is a sample implementation of producer - consumer pattern.
class BoundedBuffer {
final Lock lock = new ReentrantLock();
final Condition notFull = lock.newCondition();
final Condition notEmpty = lock.newCondition();
final Object[] items = new Object[100];
int putptr, takeptr, count;
public void put(Object x) throws InterruptedException {
lock.lock();
try {
while (count == items.length)
notFull.await();
items[putptr] = x;
if (++putptr == items.length) putptr = 0;
++count;
notEmpty.signal();
} finally {
lock.unlock();
}
}
public Object take() throws InterruptedException {
lock.lock();
try {
while (count == 0)
notEmpty.await();
Object x = items[takeptr];
if (++takeptr == items.length) takeptr = 0;
--count;
notFull.signal();
return x;
} finally {
lock.unlock();
}
}
}
Further reading: