LinkedBlockingQueue
- 基于FIFO的链表(支持无界)
- Linked queues typically have higher throughput than array-based queues but less predictable performance in most concurrent applications.
- The optional capacity bound constructor argument serves as a
way to prevent excessive queue expansion. The capacity, if unspecified,
is equal to {@link Integer#MAX_VALUE}. Linked nodes are
dynamically created upon each insertion unless this would bring the
queue above capacity. - newFixedThreadPool和newSingleThreadExecutor使用这个
- LinkedBlockingQueue是无界的,永远不会满,所以maximumPoolSize 是一个无效设定
public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>(),
threadFactory);
}
public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>(),
threadFactory));
}
ArrayBlockingQueue
基于数组的有界队列(不支持无界),FIFO
- Attempts to {@code put} an element into a full queue
will result in the operation blocking; - attempts to {@code take} an element from an empty queue will similarly block.
- 可以限制到线程池的资源占用,但是需要更小心地调节参数Queue sizes and maximum pool sizes
SynchronousQueue
- each insert operation must wait for a corresponding remove operation by another thread, and vice versa
- you cannot insert an element (using any method) unless another thread is trying to remove it
- They are well suited for handoff designs, in which an object running in one thread must sync up with an object running in another thread in order to hand it some information, event, or task.
- 同步移交队列
- newCachedThreadPool 使用这个队列,且maximumPoolSize=Integer.MAX_VALUE ```
public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue
- 要将一个元素放入SynchronousQueue,就需要有另一个线程在等待接收这个元素。若没有线程在等待,并且线程池的当前线程数小于最大值,则ThreadPoolExecutor就会新建一个线程;否则,根据饱和策略,拒绝任务。
异同
- LinkedBlockingQueue是基于链表实现的初始化是可以不用指定队列大小(默认是Integer.MAX_VALUE);ArrayBlockingQueue是基于数组实现的初始化时必须指定队列大小
- LinkedBlockingQueue在puts操作都会生成新的Node对象,takes操作Node对象在某一时间会被GC,可能会影响GC性能;ArrayBlockingQueue是固定的数组长度循环使用, 不会出现对象的产生与回收
- LinkedBlockingQueue是基于链表的形式,在执行remove操作时,不用移动其他数据;ArrayBlockingQueue是基于链表,在remove时需要移动数据,影响性能
LinkedBlockingQueue使用两个锁将puts操作与takes操作分开;ArrayBlockingQueue使用一个锁来控制,在高并发高吞吐的情况下,LinkedBlockingQueue的性能较好
- Java 并发编程 —- LinkedBlockingQueue与ArrayBlockingQueue (七)