I've got a multithreaded application with one thread putting items into a BlockingQueue
and multiple threads taking items from it for procession. The question is about taking items from the queue, currently it's implemented like this:
class PriorityQueueWorker<T> implements Runnable {
private final PriorityBlockingQueue<T> requestQueue;
private final AtomicBoolean continueExecution;
@Override
public void run() {
do {
T request = null;
try {
request = requestQueue.take();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
continueExecution.set(false);
}
if (request == null) {
continue;
}
//... here we do the work
} while (continueExecution.get());
}
According to the JavaDoc of BlockingQueue.take()
it Retrieves and removes the head of this queue, waiting if necessary until an element becomes available and for PriorityBlockingQueue
this means the thread will be blocked on PriorityBlockingQueue.take()
until an item appears in the queue:
public E take() throws InterruptedException {
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
E result;
try {
while ((result = dequeue()) == null)
notEmpty.await();
} finally {
lock.unlock();
}
return result;
}
An alternative way to implement our logic is to use PriorityBlockingQueue.poll()
which returns null
in case of empty queue:
public E poll() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
return dequeue();
} finally {
lock.unlock();
}
}
As far as I understand, the difference about these approaches is that with take()
threads are blocked on the empty queue waiting, and with poll()
they go on spinning around the infinite loop in PriorityQueueWorker.run()
.
For me the use-case when the queue is empty for a long time is quite common, so my question is which approach is better as of performance point of view: keep threads blocked (take-approach) or keep them spinning (poll-approach)?