简体   繁体   English

Java:在非阻塞队列上等待的CPU等待数已满

[英]Java: Maxed CPU Waiting on non-blocking queue

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. 其中q是ConcurrentLinkedQueue。 Currently this is eating 100% of my CPU. 目前,这占用了我100%的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? 如果q.poll()返回null,有没有办法放弃对我的线程的cpu控制?

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. 如果您无事可做,只是想等待(不使用CPU)直到数据可用,则使用阻塞队列。 That's exactly what it's made for, with methods like take : 这正是使用诸如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 : 如果您对如何实现感兴趣,可以看看这些类的源代码 ,例如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. 您可能应该对此进行基准测试,以确保它实际上比使用BlockingQueue更快。

Consider to use BlockingQueue successors. 考虑使用BlockingQueue后继程序。 In such case you do not need to iterate over empty list, thread waiting until next element in collection appears 在这种情况下,你并不需要遍历空单,线程等待 ,直到下一个元素集合中出现


public void run() {
    while (true) {
       m = q.take();
       kf.sendMessage(m.topic, m.message);
    }
}

If you have your heart set on a ConcurrentLinkedQueue , you can do something along the lines of: 如果您对ConcurrentLinkedQueue ,则可以执行以下操作:

public void run() {
  while (true) {
    m = q.poll();
    if (m != null) {
        kf.sendMessage(m.topic, m.message);
    } else Thread.yield();
  }
}

More about Thread.yield . 有关Thread.yield的更多信息。 Also consider sleeping for some small amount of time, say 50ms. 也可以考虑睡眠一段时间,例如50ms。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM