我看到了 BlockingQueue 的这些实现,无法理解它们之间的区别。到目前为止,我的结论是:

  • 我将不再需要 SynchronousQueue
  • LinkedBlockingQueue 确保FIFO,必须使用参数true创建 BlockingQueue 才能使其成为FIFO
  • SynchronousQueue 破坏了大多数收集方法(包含,大小等)

  • 因此,什么时候需要 SynchronousQueue ?此实现的性能是否比 LinkedBlockingQueue 更好?

    更复杂的是...为什么当其他人( Executors.newSingleThreadExecutor Executors.newFixedThreadPool )使用LinkedBlockingQueue时, Executors.newCachedThreadPool 为何使用SynchronousQueue?

    编辑

    第一个问题解决了。但是我仍然不明白为什么当其他人( Executors.newSingleThreadExecutor Executors.newFixedThreadPool )使用LinkedBingQueue时, Executors.newCachedThreadPool 为什么使用SynchronousQueue?

    我得到的是,使用SynchronousQueue,如果没有可用线程,生产者将被阻止。但是,由于线程数实际上是无限的(如果需要,将创建新线程),所以这永远不会发生。那么为什么要使用SynchronousQueue?

    最佳答案

    SynchronousQueue是一种非常特殊的队列-它在Queue接口(interface)的后面实现了一种集合方法(生产者等待直到消费者准备好,消费者等待直到生产者准备好)。

    因此,仅在需要特殊语义的特殊情况下才需要它,例如Single threading a task without queuing further requests

    使用SynchronousQueue的另一个原因是性能。 SynchronousQueue的实现似乎已在很大程度上进行了优化,因此,如果您只需要一个集合点(例如Executors.newCachedThreadPool(),它是按需创建消费者的,这样就不会积累队列项),您可以使用SynchronousQueue获得性能提升。

    简单的综合测试表明,在一个简单的单一生产者-单个消费者方案中,双队列机器SynchronousQueue的吞吐量比队列长度= 1的LinkedBlockingQueueArrayBlockingQueue的吞吐量高20倍左右。达到SynchronousQueue的吞吐量。这意味着与其他队列相比,SynchronousQueue在多核计算机上的同步开销较低。但是同样,仅在特定情况下,当您需要伪装成Queue的集合点时,它才重要。

    编辑:

    这是一个测试:

    public class Test {
        static ExecutorService e = Executors.newFixedThreadPool(2);
        static int N = 1000000;
    
        public static void main(String[] args) throws Exception {
            for (int i = 0; i < 10; i++) {
                int length = (i == 0) ? 1 : i * 5;
                System.out.print(length + "\t");
                System.out.print(doTest(new LinkedBlockingQueue<Integer>(length), N) + "\t");
                System.out.print(doTest(new ArrayBlockingQueue<Integer>(length), N) + "\t");
                System.out.print(doTest(new SynchronousQueue<Integer>(), N));
                System.out.println();
            }
    
            e.shutdown();
        }
    
        private static long doTest(final BlockingQueue<Integer> q, final int n) throws Exception {
            long t = System.nanoTime();
    
            e.submit(new Runnable() {
                public void run() {
                    for (int i = 0; i < n; i++)
                        try { q.put(i); } catch (InterruptedException ex) {}
                }
            });
    
            Long r = e.submit(new Callable<Long>() {
                public Long call() {
                    long sum = 0;
                    for (int i = 0; i < n; i++)
                        try { sum += q.take(); } catch (InterruptedException ex) {}
                    return sum;
                }
            }).get();
            t = System.nanoTime() - t;
    
            return (long)(1000000000.0 * N / t); // Throughput, items/sec
        }
    }
    

    这是我的机器上的结果:

    关于java - BlockingQueue : What are the differences between SynchronousQueue and LinkedBlockingQueue的实现,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/5102570/

    10-09 07:15