为什么在使用LinkedBlockingQueue时使用ConcurrentLinkedQueue?

时间:2018-04-15 14:24:59

标签: java multithreading concurrency

为什么我ConcurrentLinkedQueue时会使用LinkedBlockingQueue?我知道ConcurrentLinkedQueue是非阻止的,但LinkedBlockingQueue可以作为ConcurrentLinkedQueue使用。我会使用put() / offer()方法进行插入,并使用poll()方法进行删除。如果队列为空,poll()方法不会等待。 LinkedBlockingQueue也是无限的。所以我可以用它。

到目前为止我发现的差异是ConcurrentLinkedQueue正在使用硬件级同步机制进行比较和交换,而LinkedBlockingQueue正在使用ReentrantLock

1 个答案:

答案 0 :(得分:5)

主要区别在于ConcurrentLinkedQueue 等待免费,而不仅仅是无锁what's the difference?LinkedBlockingQueue必须保持锁定的本质。

您可以使用ConcurrentLinkedQueueLinkedBlockingQueuepoll进行建模,但实现仍将保持锁定状态,从而降低您可能从系统中获得的并发性。

这是一个公认的不精确的微基准测试,可以检查通过两个并发队列中的每个队列传递10,000个对象的速度而不会阻塞,并计算循环中poll()的调用总数:

AtomicInteger total = new AtomicInteger();
ConcurrentLinkedQueue<Integer> q = new ConcurrentLinkedQueue<>();
Thread thread = new Thread(() -> {
    int remaining = 10000;
    while (remaining != 0) {
        total.incrementAndGet();
        if (q.poll() != null) {
            remaining--;
        }
    }
});
Integer[] first100 = new Integer[100];
for (int i = 0 ; i != 100 ; i++) {
    first100[i] = i;
}
long start = System.nanoTime();
thread.start();
for (int i = 0 ; i != 10000 ; i++) {
    q.add(first100[i%100]);
}
thread.join();
long runtime = System.nanoTime() - start;

这个想法是在没有其他处理的情况下测量队列的“吞吐量”。此任务在11.23 ms内完成,读取线程(demo 1)中的ConcurrentLinkedQueue进行了60K次迭代,LinkedBlockingQueuedemo 2)进行了23,46 ms / 100K次迭代。< / p>