`
wwty
  • 浏览: 542868 次
  • 性别: Icon_minigender_1
  • 来自: 北京-郑州
社区版块
存档分类
最新评论

使用ConcurrentLinkedQueue惨痛的教训

阅读更多

文章来源:

http://blog.csdn.net/Kanepan/archive/2010/07/01/5706488.aspx

 

前两天写了个生产消费的程序,根据需求用了ConcurrentLinkedQueue,然后又用到了其size方法,所以转载此篇文章。

 

服务端原本有个定时任务对一个集合ArrayList 中的消息做处理。 因为考虑到处理消息是先进先出原则,所以优化的时候考虑改用ConcurrentLinkedQueue 当时没仔细深入研究过这个集合就匆匆上线了。结果刚上线第二天就出问题了。服务端一次优化演变成了一个缺陷,还好及时回退了版本,后果才不是很严重。

回退后对ConcurrentLinkedQueue 做了一个简单的测试代码如下:

view plaincopy to clipboardprint?
import java.util.concurrent.ConcurrentLinkedQueue;  
import java.util.concurrent.CountDownLatch;  
import java.util.concurrent.ExecutorService;  
import java.util.concurrent.Executors;  
public class ConcurrentLinkedQueueTest {  
    private static ConcurrentLinkedQueue<Integer> queue = new ConcurrentLinkedQueue<Integer>();  
    private static int count = 100000;  
    private static int count2 = 2; // 线程个数  
    private static CountDownLatch cd = new CountDownLatch(count2);  
    public static void dothis() {  
        for (int i = 0; i < count; i++) {  
            queue.offer(i);  
        }  
    }  
    public static void main(String[] args) throws InterruptedException {  
        long timeStart = System.currentTimeMillis();  
        ExecutorService es = Executors.newFixedThreadPool(4);  
        ConcurrentLinkedQueueTest.dothis();  
        for (int i = 0; i < count2; i++) {  
            es.submit(new Poll());  
        }  
        cd.await();  
        System.out.println("cost time "  
                + (System.currentTimeMillis() - timeStart) + "ms");  
        es.shutdown();  
    }  
    static class Poll implements Runnable {  
        @Override  
        public void run() {  
//          while (queue.size()>0) {  
            while (!queue.isEmpty()) {  
                System.out.println(queue.poll());  
            }  
            cd.countDown();  
        }  
    }  
}  

 

运行结果:

costtime 2360ms

改用while (queue.size()>0)后

运行结果:

cost time 46422ms

结果居然相差那么大,看了下ConcurrentLinkedQueue的API 原来.size() 是要遍历一遍集合的,难怪那么慢,所以尽量要避免用size而改用isEmpty().

总结了下, 在单位缺乏性能测试下,对自己的编程要求更加要严格,特别是在生产环境下更是要小心谨慎。

分享到:
评论
3 楼 287854442 2011-08-26  
有必要这样实现吗?
queue.poll()方法如果队列为空,返回null
可以这样实现:
while(true){
     Integer i = queue.poll();
     if (i==null){
          break;
     }else{
           syso(i);
     }
}

2 楼 wwty 2011-06-22  
xnxqs 写道
你这个程序还是有隐患的。。。
while (!queue.isEmpty()) {   
                System.out.println(queue.poll());   
            } 

poll涉及到删除元素的动作,而这一部分的操作已经是原子性的了,所以你必须加锁,可以参考这个。http://stackoverflow.com/questions/435069/java-util-concurrentlinkedqueue/435941


呵呵,谢谢了,确实是这样:
That last one is not threadsafe, as it is very possible that between the time isEmpty is called and the time poll is called, other threads will have added or removed items from the queue. The threadsafe way to perform this is like this:

synchronized(queue) {
    if(!queue.isEmpty()) {
       queue.poll(obj);
    }
}
1 楼 xnxqs 2011-06-20  
你这个程序还是有隐患的。。。
while (!queue.isEmpty()) {   
                System.out.println(queue.poll());   
            } 

poll涉及到删除元素的动作,而这一部分的操作已经是原子性的了,所以你必须加锁,可以参考这个。http://stackoverflow.com/questions/435069/java-util-concurrentlinkedqueue/435941

相关推荐

    自己动手让springboot异步处理浏览器发送的请求(只需要使用ConcurrentLinkedQueue即可)

    本文将详细介绍如何使用Java中的`ConcurrentLinkedQueue`数据结构,结合Spring Boot的特性,实现异步处理浏览器发送的请求。 首先,`ConcurrentLinkedQueue`是Java并发包`java.util.concurrent`中的一个无界线程...

    ConcurrentLinkedQueue源码分析.rar

    在`ConcurrentLinkedQueue`中,插入操作(`add()`)和删除操作(`poll()`)都使用了CAS(Compare and Swap)操作,这是一种无锁算法,通过原子地比较并更新内存中的值来实现并发控制。这种无锁机制避免了线程间的...

    LinkedBlockingQueue 和 ConcurrentLinkedQueue的区别.docx

    ConcurrentLinkedQueue使用了高级并发原语,如 CAS(Compare and Swap),以非阻塞方式实现队列操作。当队列为空时,尝试获取元素的线程不会被阻塞,而是立即返回null。尽管无界,但内存限制仍然存在,若无法分配更...

    ConcurrentLinkedQueue

    ConcurrentLinkedQueue

    并发队列ConcurrentLinkedQueue和阻塞队列LinkedBlockingQueue用法

    下面通过一个具体的例子来说明如何使用 `LinkedBlockingQueue`: ```java import java.util.concurrent.*; public class BlockingQueueTest2 { // 定义一个篮子类 public class Basket { // 初始化篮子的容量...

    聊聊并发(6)ConcurrentLinkedQueue的

    这种数据结构允许在不加锁的情况下进行插入和删除操作,这是通过使用 CAS(Compare and Swap)原子指令实现的。CAS 是一种硬件支持的原子操作,能够在多线程环境下保证操作的原子性,避免了锁的开销,提升了并发性能...

    Java 多线程与并发(15-26)-JUC集合- ConcurrentLinkedQueue详解.pdf

    - **Unsafe类**:为了提高性能,`ConcurrentLinkedQueue`使用了`Unsafe`类来进行底层操作,比如内存访问等。通过这种方式,可以在一定程度上避免锁带来的开销。 #### 五、应用场景 - **生产者消费者模型**:`...

    Java 线程 ? ConcurrentLinkedQueue

    ConcurrentLinkedQueue  在考虑并发的时候可以先考虑单线程的情况,然后再将并发的情况考虑进来。  比如ConcurrentLinkedQueue:  1、先考虑单线的offer  2、再考虑多线程时候的offer:  · 多个线程offer...

    Java concurrency集合之ConcurrentLinkedQueue_动力节点Java学院整理

    ConcurrentLinkedQueue提供了丰富的API供开发者使用: 1. `ConcurrentLinkedQueue()`:构造一个空的队列。 2. `ConcurrentLinkedQueue(Collection&lt;? extends E&gt; c)`:根据给定的集合创建队列。 3. `add(E e)`:向...

    使用-Java-构造高可扩展应用

    使用 Java 构造高可扩展应用需要遵循一些简单规则和工具,例如使用 LockFreeQueue 替换标准库中的 ConcurrentLinkedQueue,检测锁的使用和冲突,等等。本文提供了一些实用的经验和建议,帮助开发人员提高 Java 多...

    Java并发编程相关源码集 包括多任务线程,线程池等.rar

    Java并发编程常见知识点源码集锦,涉及到对象锁,Executors多任务线程框架,线程池等... ConcurrentLinkedQueue、DelayQueue示例、自定义的线程拒绝策略、自定义线程池(使用有界队列)、自定义线程池(使用无界队列)。。。

    实战Concurrent-BlockQueue

    本文将深入探讨`ConcurrentLinkedQueue`、`ArrayBlockingQueue`以及`LinkedBlockingQueue`这三种实现,并分析它们的设计原理与应用场景。 首先,我们来看`ConcurrentLinkedQueue`。它是基于非阻塞算法(CAS,...

    线程安全的jdbc连接池

    在这个简单的实现中,我们利用了`ConcurrentLinkedQueue`数据结构来确保多线程环境下的安全性和效率。 首先,让我们了解什么是JDBC连接池。JDBC连接池(Java Database Connectivity Connection Pool)是数据库资源...

    Java并发编程原理与实战

    并发容器ConcurrentLinkedQueue原理与使用.mp4 Java中的阻塞队列原理与使用.mp4 实战:简单实现消息队列.mp4 并发容器ConcurrentHashMap原理与使用.mp4 线程池的原理与使用.mp4 Executor框架详解.mp4 实战:简易web...

    Java编程中“为了性能”需做的26件事

    22. **使用并发容器**:如ConcurrentHashMap和ConcurrentLinkedQueue,它们专为多线程环境设计,提高并发性能。 23. **使用软引用和弱引用**:这些引用可以帮助控制内存,防止内存泄漏,同时提高内存使用效率。 24...

    Java语言编程规范--华为技术有限公司

    - 避免使用`ArrayList`进行并发操作,考虑使用`CopyOnWriteArrayList`或`ConcurrentLinkedQueue`。 - 清理不再使用的集合,避免内存泄漏。 8. **并发编程** - 使用并发工具类如`Semaphore`、`ExecutorService`,...

    Android eventbus

    - **事件容器**:存储待分发的事件,可以使用`ConcurrentLinkedQueue`这样的并发队列。 - **订阅者管理**:维护一个订阅者列表,记录订阅者的事件类型和回调方法。 - **线程模式**:处理事件的线程模型,如主线程、...

    JAVA高并发包介绍

    接下来,我们来深入探讨几个在并发编程中经常用到的数据结构,以及它们的概念、原理、数据结构和使用场景。 首先,我们来看ConcurrentSkipListMap。它是Java并发包中一个线程安全的有序映射表,基于跳表(Skip List...

    java代码优化细节总结1.0版本.zip

    可以考虑使用并发工具类,如`AtomicInteger`、`ConcurrentLinkedQueue`等。 9. **合理使用数据结构**:选择合适的数据结构能显著提高性能。例如,使用Set而非List来保证元素唯一性,使用TreeMap而非HashMap实现有序...

    并发容器的原理,7大并发容器详解、及使用场景

    4. ConcurrentLinkedQueue 是一个基于链接节点的无界并发队列,它使用了链表结构实现 FIFO(先进先出),并且不使用锁,而是依赖于 CAS 操作。 5. LinkedBlockingQueue、ArrayBlockingQueue 和 ...

Global site tag (gtag.js) - Google Analytics