Java:非阻塞队列上的最大CPU等待

时间:2014-04-29 23:02:24

标签: java concurrency

我有以下代码:

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的控制?

我可以选择切换到阻塞队列,但我很好奇这样做的正确方法是什么。

编辑 - 很多好的回复!感谢你的帮助。现在我要切换到一个链接块,如果我开始遇到性能问题重新评估。

4 个答案:

答案 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。