java.util.ConcurrentLinkedQueue

2022-09-02 22:53:51

我想使用java.util.ConcurrentLinkedQueue作为Servlet的非持久队列。这是来自javadoc的类的简介。

基于链接节点的无界线程安全队列。当许多线程将共享对公共集合的访问权限时,ConcurrentLinkedQueue 是一个合适的选择。此队列不允许空元素。

现在假设我在 servlet 上有 1000 个并发请求,每个线程都需要将一个对象引入 ConcurrentLinkedQueue。从描述中,我是否应该得出结论,它在处理负载时不会有问题?我需要的保证是:

  1. 我会自动收到线程安全保证,而无需进行自己的同步。
  2. 如果流量负载超过 1000 个并发请求,我不会丢失任何请求。

谢谢


答案 1

你基本上是在问三个不同的问题(其中两个是明确的,一个是隐含的)。他们在这里,我的答案是:

1. 如果我使用 java.util.ConcurrentLinkedQueue,我是否需要自己进行同步?

并发集合上的原子操作将为您同步。换句话说,对队列的每个单独调用都保证线程安全,而无需您执行任何操作。不能保证线程安全的是对集合执行的任何非原子操作。

例如,这是线程安全的,您无需执行任何操作:

queue.add(obj);

queue.poll(obj);

但是;对队列的非原子调用不会自动实现线程安全。例如,以下操作不会自动提供线程安全:

if(!queue.isEmpty()) {
   queue.poll(obj);
}

最后一个线程不是线程安全的,因为在调用时间 isEmpty 和调用轮询时间之间,其他线程很可能在队列中添加或删除了项目。执行此操作的线程安全方法如下所示:

synchronized(queue) {
    if(!queue.isEmpty()) {
       queue.poll(obj);
    }
}

再。。。对队列的原子调用是自动线程安全的。非原子调用不是。

2. 如果有 1000 个并发请求,我能保证不会丢失对 java.util.ConcurrentLinkedQueue 的调用吗?

因为这是一个无限的实现,所以可以保证无论同时发出多少个请求,队列都不会丢失这些请求(因为队列的并发性...你可能会用完内存或一些类似的...但队列实现本身不会是你的限制因素。在 Web 应用程序中,还有其他机会“丢失”请求,但队列的同步(或缺少同步)不会是您的原因。

3. java.util.ConcurrentLinkedQueue 的性能是否足够好?

通常,当我们谈论并发性时,我们谈论“正确性”。我的意思是,Concurrent 类保证它们是线程安全的(或者对死锁、饥饿等具有健壮性)。当我们谈论这一点时,我们并没有对性能做出任何保证(对集合的调用速度有多快) - 我们只是保证它们是“正确的”。

但是;ConcurrentLinkedQueue是一个“无等待”的实现,所以这可能是你能得到的最好的。保证 servlet 的加载性能(包括使用并发类)的唯一方法是在加载下对其进行测试。


答案 2

请记住,队列仅对单个成员的调用提供线程安全。不要像这样编写代码,并期望它能正常工作:

if (queue.Count!=0)
    queue.Dequeue().DoSomething();

在这两个操作之间,另一个线程可能已将最后一个元素取消排队。我对Java集合并不亲密,但我想在这种情况下Dequeue会返回,给你一个例外。null


推荐