java - ConcurrentLinkedQueue 的替代方案,我是否需要使用带锁的 LinkedList?
问题描述
我目前正在使用 ConcurrentLinkedQueue,这样我就可以使用自然顺序 FIFO 并在线程安全应用程序中使用它。我需要每分钟记录一次队列的大小,并且鉴于此集合不保证大小并且计算大小的成本为 O(N),是否有任何替代的有界非阻塞并发队列可以在获取时使用size 不会是一项昂贵的操作,同时添加/删除操作也不昂贵?
如果没有集合,我需要使用带锁的LinkedList吗?
解决方案
如果您真的(真的)需要记录Queue
您当前正在处理的正确的当前大小 - 您需要阻止。根本没有别的办法。您可以认为维护一个单独的LongAdder
字段可能会有所帮助,可能是将您自己的界面作为包装器ConcurrentLinkedQueue
,例如:
interface KnownSizeQueue<T> {
T poll();
long size();
}
和一个实现:
static class ConcurrentKnownSizeQueue<T> implements KnownSizeQueue<T> {
private final ConcurrentLinkedQueue<T> queue = new ConcurrentLinkedQueue<>();
private final LongAdder currentSize = new LongAdder();
@Override
public T poll() {
T result = queue.poll();
if(result != null){
currentSize.decrement();
}
return result;
}
@Override
public long size() {
return currentSize.sum();
}
}
我只是鼓励您再添加一种方法,例如remove
在界面中并尝试对代码进行推理。您很快就会意识到,这样的实现仍然会给您错误的结果。所以,不要这样做。
如果您真的需要它,获取大小的唯一可靠方法是阻止每个操作。这是要付出高昂代价的,因为ConcurrentLinkedQueue
记录为:
该实现采用了高效的非阻塞...
您将失去这些属性,但如果这是一个不关心的硬性要求,您可以编写自己的:
static class ParallelKnownSizeQueue<T> implements KnownSizeQueue<T> {
private final Queue<T> queue = new ArrayDeque<>();
private final ReentrantLock lock = new ReentrantLock();
@Override
public T poll() {
try {
lock.lock();
return queue.poll();
} finally {
lock.unlock();
}
}
@Override
public long size() {
try {
lock.lock();
ConcurrentLinkedQueue
return queue.size();
} finally {
lock.unlock();
}
}
}
或者,当然,您可以使用已经存在的结构,例如LinkedBlockingDeque
orArrayBlockingQueue
等 - 取决于您的需要。
推荐阅读
- r - 将年份向量转换为具有范围间隔的单个字符串
- python - 在 python 中用于打印格式时无法打印字典值
- c++ - 在 wxWidgets 中将字符串存储为 wstring 或 wxString?
- java - Facebook Android SDK:“无法解析符号 EVENT_NAME_SUBSCRIBE”
- ssis - 在 ADO 网络源的 SQL 命令 SSIS 中使用变量
- python - 我怎样才能让这个二分搜索工作?
- python - 如何使用 python csv 或 pandas 模块水平组合多个 CSV 文件?
- python - 在 python 中的 Wxpython 中第二次打印时出错
- django - Django 添加第二个静态文件 URL
- python - 在python中将类返回给自身