I have the following code:
public void run() {
while (true) {
m = q.poll();
if (m != null) {
kf.sendMessage(m.topic, m.message);
}
}
}
where q is a ConcurrentLinkedQueue. Currently this is eating 100% of my CPU. Is there a more efficient way to wait on a non-blocking queue? I prefer to use a non-blocking queue because I am expecting bursty traffic from the producers on the queue, so I want to maximize performance. Is there a way to relinquish control of the cpu for my thread if q.poll() returns null?
I have the option of switching to a blocking queue, but I am curious what the proper way of doing this is.
Edit - Lots of good responses! Thanks for all your help. For now I'm going to just switch to a linkedblockqueue, and if I start running into performance issues re-evaluate.
If you have nothing else to do, and just want to wait (without using CPU) until data is available, then use a blocking queue. That's exactly what it's made for, with methods like take
:
Retrieves and removes the head of the queue represented by this deque (in other words, the first element of this deque), waiting if necessary until an element becomes available.
If you are interesting in how this is implemented, you can take a look at the source for these classes, for example LinkedBlockingQueue#take
:
public E take() throws InterruptedException {
E x;
int c = -1;
final AtomicInteger count = this.count;
final ReentrantLock takeLock = this.takeLock;
takeLock.lockInterruptibly();
try {
while (count.get() == 0) {
notEmpty.await();
}
x = dequeue();
c = count.getAndDecrement();
if (c > 1)
notEmpty.signal();
} finally {
takeLock.unlock();
}
if (c == capacity)
signalNotFull();
return x;
}
As you can see, they maintain a couple of Conditions to signal if the queue is empty or not.
Since you're dealing with bursty behavior, you could wait when you've checked the queue and it's empty.
while (true) {
m = q.poll();
if (m != null) {
kf.sendMessage(m.topic, m.message);
} else {
// Queue was empty, wait for a little while
// Adjust time based on your requirements
Thread.sleep(100);
}
}
You should probably benchmark this to make sure it's actually faster than using a BlockingQueue
though.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With