我有以下代码:
public void run() {
while (true) {
m = q.poll();
if (m != null) {
kf.sendMessage(m.topic, m.message);
}
}
}
其中q是ConcurrentLinkedQueue。目前这是占用我100%的CPU。有没有更有效的方法来等待非阻塞队列?我更喜欢使用非阻塞队列,因为我期待来自队列中生产者的突发流量,所以我想要最大化性能。如果q.poll()返回null,有没有办法放弃对我的线程的cpu的控制?
我可以选择切换到阻塞队列,但我很好奇这样做的正确方法是什么。
编辑 - 很多好的回复!感谢你的帮助。现在我要切换到一个链接块,如果我开始遇到性能问题重新评估。
答案 0 :(得分:3)
如果您没有其他任何事情可做,只想在数据可用之前等待(不使用CPU),则使用阻塞队列。这正是它所做的,使用take
等方法:
检索并删除此双端队列表示的队列的头部(换句话说,此双端队列的第一个元素),必要时等待,直到元素可用。
如果您对如何实施这些内容感兴趣,可以查看这些类的the source,例如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;
}
正如您所看到的,如果队列为空,他们会保留几个Conditions来表示。
答案 1 :(得分:1)
由于您正在处理突发行为,因此您可以等待检查队列并且它已空。
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);
}
}
你应该对此进行基准测试,以确保它实际上比使用BlockingQueue
更快。
答案 2 :(得分:0)
考虑使用BlockingQueue后继者。在这种情况下,你不需要迭代对空列表,线程等待,直到集合中的下一个元素出现
public void run() {
while (true) {
m = q.take();
kf.sendMessage(m.topic, m.message);
}
}
答案 3 :(得分:0)
如果你的心脏设置在ConcurrentLinkedQueue
,你可以采取以下措施:
public void run() {
while (true) {
m = q.poll();
if (m != null) {
kf.sendMessage(m.topic, m.message);
} else Thread.yield();
}
}
有关Thread.yield的更多信息。也请考虑sleeping一段时间,比如说50ms。