gpt4 book ai didi

java - LinkedBlockingQueue .take() 性能

转载 作者:行者123 更新时间:2023-12-01 06:45:13 24 4
gpt4 key购买 nike

我正在使用由多个线程填充的LinkedBlockingQueue,项目数量很大(数千万个对象)。

LinkedBlockingQueue.take() 需要大量时间(通过探查器检查) - 56% 的时间。
队列永远不会空!!

什么会影响 take() 方法的性能?

更新:我对处理 take() 结果的代码做了一些更改,我还将 take() 放入另一个线程中,性能提高了近 50%。

我不明白这是怎么可能的,因为我没有改变推杆的任何逻辑......

更新:

在调用 take() 之前,我计算了队列已满的次数:
使用原始代码,90% 的调用队列已满。
通过改进代码,13% 的调用队列已满。

最佳答案

如果我们看一下代码 here我们可以看到,在获取元素之前必须先获取锁。如果有很多线程正在获取,那么就会出现对该锁的争用 - 线程不会等待某些东西出现,而是等待其他线程获取东西。

 public E take() throws InterruptedException {
E x;
int c = -1;
final AtomicInteger count = this.count;
final ReentrantLock takeLock = this.takeLock;
takeLock.lockInterruptibly();
try {
try {
while (count.get() == 0)
notEmpty.await();
} catch (InterruptedException ie) {
notEmpty.signal(); // propagate to a non-interrupted thread
throw ie;
}

x = extract();
c = count.getAndDecrement();
if (c > 1)
notEmpty.signal();
} finally {
takeLock.unlock();
}
if (c == capacity)
signalNotFull();
return x;
}

编辑

如果您有一个接受者和许多推杆,并且队列不断变满,则瓶颈将变为此代码给出的 signalNotFull()

private void signalNotFull() {
final ReentrantLock putLock = this.putLock;
putLock.lock();
try {
notFull.signal();
} finally {
putLock.unlock();
}
}

这需要使用 putLock 来表明队列中现在有空间。

关于java - LinkedBlockingQueue .take() 性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17193840/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com