当前位置: 首页 > 知识库问答 >
问题:

替代并发LinkedQueue,我需要使用带锁的LinkedList吗?

郁高韵
2023-03-14

我目前正在使用一个并发链接队列,这样我就可以使用自然顺序FIFO,也可以在线程安全的应用程序中使用它。我需要每分钟记录队列的大小,并且考虑到此集合不保证大小,并且计算大小的成本为O(N),是否有任何替代的有界非阻塞并发队列,我可以在获取大小不会是一个昂贵的操作的地方使用,同时添加/删除操作也不昂贵?

如果没有集合,我需要使用带锁的LinkedList吗?

共有1个答案

仉磊
2023-03-14

如果您确实(实际上)需要记录当前正在处理的队列的正确当前大小 - 则需要阻止。根本没有其他办法。你可以认为维护一个单独的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();
    }
}

我只是鼓励您再添加一个方法,例如删除到接口中并尝试推理代码。您很快就会意识到,这样的实现仍然会给您错误的结果。所以,不要这样做。

如果您真的需要,获取大小的唯一可靠方法是为每个操作阻塞。这代价很高,因为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();
        }
    }
}

当然,你也可以使用一个已经存在的结构,比如< code > linkedblockingqueue 或者< code>ArrayBlockingQueue等等——这取决于你的需要。

 类似资料:
  • 我需要一个线程安全的并发列表,同时最适合迭代,并且应该返回精确的大小。我想存储物品的拍卖出价。所以我想能够 检索项目的确切出价数量 为项目添加出价 检索给定项目的所有出价。 移除商品出价 我打算把它放在

  • 我现在正在寻找一个线程安全的程序,允许我在程序中实现时间优先级。如果你愿意,我很乐意与你分享代码,但我认为这对我的问题并不重要。当我开始运行这个程序的一个(非线程安全)版本时,我最初使用的是一个链表,但是现在我切换到了一个线程安全的版本,我已经从一个链表变成了一个并发链接队列。问题是我需要从队列中获取元素(通常从头部,偶尔从尾部)。我真的只需要看看头部的元素是否满足某个性质。在链表版本中,它看起来

  • 问题内容: 在Linux(内核2.6.5)上,我们的构建系统使用调用gcc 。 使用时仍然需要吗? 它与期权有什么关系?我知道我应该与pthreads一起使用,还需要吗? 附带说明一下,您在gcc 3.3.3和gcc 4.xx之间使用REENTRANT有什么区别吗? 当我使用gcc选项时,可以看到已定义。从命令行省略是否会有所不同,例如某些对象可以在没有多线程支持的情况下进行编译,然后链接到使用p

  • 我已经创建了一个facebook应用程序,并检索了有效期为60天的用户访问令牌。 在Android系统中,有一些东西 public void onResume(){ super.onResume();facebook.extendedcesstokenifneeded(此,null);} 这将扩展accesstoken(如果它即将过期)。PHP中是否有类似的替代方案?因此,60天后,令牌将刷新,而

  • 问题内容: 如果我正确使用通道,是否需要使用互斥锁来防止并发访问? 问题答案: 如果正确使用通道,则不需要互斥。在某些情况下,使用互斥锁的解决方案可能会更简单。 只需确保包含通道值的变量已正确初始化,然后使用多个goroutine尝试访问通道变量即可。一旦完成,按设计访问通道(例如,向它们发送值或从中接收值)是安全的。 带有参考文献的证明文件(重点由我添加): 规格:渠道类型: 单个信道 ,可以使

  • 问题内容: 如果我想编码node.js并使用CoffeeScript,我有哪些限制?我可以做一些我在JS中可以做的事情吗? 问题答案: 是的,CoffeeScript可以简单地编译为纯JS,使其与node.js完全兼容。 要在节点上运行CoffeeScripts,您可以: 键入要编译的代码,然后运行已编译的JS。 只需输入