(五)java 线程池工作队列

线程池工作队列

  上一章我们介绍了线程的基本情况,这一章进一步了解线程池中的工作队列,BlockingQueue 队列。

在类 Executors 中,我们可以看到不同线程池维护的工作队列是不同的,如newCachedThreadPool使用的是SynchronousQueue 同步队列,newSingleThreadScheduledExecutor使用DelayedWorkQueue
newFixedThreadPoolnewScheduledThreadPool使用LinkedBlockingQueue。它们都是实现了并发包java.util.concurrent中的BlockingQueue,下面说说这个接口。

BlockingQueue 阻塞队列

继承于队列 Queue,遵循先进先出原则(FIFO),队列提供几种基本的操作,添加元素(队尾)、移除元素(队头)、取出队头元素(不移除),每种操作都有两个方法,一种有可能抛异常,一种返回操作成功或失败。

在这个基础上,阻塞队列增加了操作锁,保证了数据安全,当然这个具体实现是在子类中完成,接口仅仅描述方法的特点,还增加两种不同的操作实现。下面描述这四种不同类型的操作:

  1. 操作,可能抛异常
  2. 操作,不抛异常(特殊如类转换异常、空指针、参数异常不属于,仅当队列已满不会跑状态异常)
  3. 无限期阻塞线程直至操作成功
  4. 有时间限制的操作
添加 移除 检查
add(e) remove(o) element()
offer(e) poll() peek()
put(e) take() \
offer(e,time,unit) poll(time,unit) \

以及增加了拷贝 drainTo,如线程池的 shutdownNow就是用它完成工作队列的清除以及队列中数据的拷贝,还有其他如对比元素contains,剩余容量查询remainingCapacity等。

实现的子类

  1. ArrayBlockingQueue 数组型阻塞队列
  2. LinkedBlockingQueue 链表型阻塞队列
  3. DelayQueue 延时队列
  4. SynchronousQueue 同步队列
  5. PriorityBlockingQueue 优先阻塞队列

ArrayBlockingQueue

特点:

  1. 初始化一定容量的数组
  2. 使用一个重入锁,默认使用非公平锁,入队和出队共用一个锁,互斥
  3. 是有界设计,如果容量满无法继续添加元素直至有元素被移除
  4. 使用时开辟一段连续的内存,如果初始化容量过大容易造成资源浪费,过小易添加失败

LinkedBlockingQueue

特点:

  1. 内部使用节点关联,会产生多一点内存占用
    • 使用两个重入锁分别控制元素的入队和出队,用Condition进行线程间的唤醒和等待
    • 有边界的,在默认构造方法中容量是Integer.MAX_VALUE
    • 非连续性内存空间
DelayQueue

特点:

  1. 无边界设计
  2. 添加(put)不阻塞,移除阻塞
  3. 元素都有一个过期时间
  4. 取元素只有过期的才会被取出
SynchronousQueue

特点:

  1. 内部容量是0
  2. 每次删除操作都要等待插入操作
  3. 每次插入操作都要等待删除操作
  4. 一个元素,一旦有了插入线程和移除线程,那么很快由插入线程移交给移除线程,这个容器相当于通道,本身不存储元素
  5. 在多任务队列,是最快的处理任务方式。

一篇关于 SynchronousQueue 的文章

PriorityBlockingQueue

特点:

  1. 无边界设计,但容量实际是依靠系统资源影响
  2. 添加元素,如果超过1,则进入优先级排序

你可能感兴趣的:(java,线程)