我看到了 BlockingQueue 的这些实现,无法理解它们之间的区别。到目前为止,我的结论是:
因此,什么时候需要 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的LinkedBlockingQueue
和ArrayBlockingQueue
的吞吐量高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/