文章目录
BlockingQueue
阻塞队列接口,继承Queue接口,是一个先进先出的队列,提供阻塞获取和添加元素的方法
public interface BlockingQueue<E> extends Queue<E> {
//抛出异常的获取方法
boolean add(E e);
boolean remove(Object o);
E element();
//不抛出异常的获取方法
boolean offer(E e);
E poll();
E peek();
//阻塞获取的方法
E take() throws InterruptedException;
void put(E e) throws InterruptedException;
//阻塞直到成功或超时
boolean offer(E e, long timeout, TimeUnit unit)
throws InterruptedException;
E poll(long timeout, TimeUnit unit)
throws InterruptedException;
//从该队列中删除所有可用的元素,并将它们添加到给定的集合中
int drainTo(Collection<? super E> c);
//返回该队列可以接受而不会阻塞的元素数量
int remainingCapacity();
}
ArrayBlockingQueue有界队列
一个有界阻塞队列,底层采用数组实现,使用可重入锁(可选公平和非公平)和两个条件监视器来控制同步。对读写操作都加锁。
成员变量
//等待队列
final Object[] items;
//take, poll, peek or remove操作的下一次索引位置
int takeIndex;
//put, offer, or add操作的下一次索引位置
int putIndex;
//队列数量
int count;
//并发控制的锁和监视器
final ReentrantLock lock;
private final Condition notEmpty;
private final Condition notFull;
构造方法
//默认不公平锁
public ArrayBlockingQueue(int capacity) {
this(capacity, false);
}
public ArrayBlockingQueue(int capacity, boolean fair) {
if (capacity <= 0)
throw new IllegalArgumentException();
//初始化数组大小、锁和监视器
this.items = new Object[capacity];
lock = new ReentrantLock(fair);
notEmpty = lock.newCondition();
notFull = lock.newCondition();
}
重要方法
enqueue(E x)
添加节点执行的操作
private void enqueue(E x) {
// assert lock.getHoldCount() == 1;
// assert items[putIndex] == null;
final Object[] items = this.items;
//在当前位置插入节点
items[putIndex] = x;
//当到达数组尾部,重新指向0位置,数组模拟队列操作
//当putIndex =0时说明执行了出队操作,此时takeIndex指向1了
if (++putIndex == items.length)
putIndex = 0;
count++;
//唤醒所有在队列为空等待的线程
notEmpty.signal();
}
dequeue()
删除节点执行的操作
private E dequeue() {
// assert lock.getHoldCount() == 1;
// assert items[takeIndex] != null;
final Object[] items = this.items;
@SuppressWarnings("unchecked")
//获得旧值
E x = (E) items[takeIndex];
//删除位置设置为null
items[takeIndex] = null;
//当出队索引等于数组长度,索引重新指向0
if (++takeIndex == items.length)
takeIndex = 0;
count--;
if (itrs != null)
itrs.elementDequeued();
//唤醒所有在队列已满等待的线程
notFull.signal();
return x;
}
LinkedBlockingQueue无界队列
LinkedBlockingQueue是基于链表的无界队列(有最大值Integer.MAX_VALUE),不同于ArrayBlockingQueueQueue,LinkedBlockingQueue使用两个重入锁(非公平)来分别控制进队和出队操作,提高了吞吐量。
成员变量
//链表大小
private final int capacity;
//链表中元素个数(原子类)
private final AtomicInteger count = new AtomicInteger();
//链表的头结点(空节点)
transient Node<E> head;
//链表的尾结点
private transient Node<E> last;
//take, poll等操作的锁
private final ReentrantLock takeLock = new ReentrantLock();
//队列为空的等待监视器
private final Condition notEmpty = takeLock.newCondition();
//put, offer等操作的锁
private final ReentrantLock putLock = new ReentrantLock();
//队列已满的等待监视器
private final Condition notFull = putLock.newCondition();
构造方法
//默认初始大小为Integer.MAX_VALUE
public LinkedBlockingQueue() {
this(Integer.MAX_VALUE);
}
//自定义初始大小
public LinkedBlockingQueue(int capacity) {
if (capacity <= 0) throw new IllegalArgumentException();
this.capacity = capacity;
last = head = new Node<E>(null);
}
内部类Node
表示LinkedBlockingQueue队列中的节点,可以看出该队列为一个单向队列
static class Node<E> {
E item;
//队列中下一个元素
Node<E> next;
Node(E x) { item = x; }
}
重要方法
enqueue(Node node)
入队操作
private void enqueue(Node<E> node) {
// assert putLock.isHeldByCurrentThread();
// assert last.next == null;
//将节点加入到尾结点的next节点上,并将尾结点设置为当前节点
last = last.next = node;
}
dequeue()
出队操作
private E dequeue() {
// assert takeLock.isHeldByCurrentThread();
// assert head.item == null;
//head节点为一个空节点,只有next有值
Node<E> h = head;
//移除头结点head节点
Node<E> first = h.next;
h.next = h; // help GC
//将头结点设置为真实被移除节点,因为该节点item移除后为空
head = first;
E x = first.item;
first.item = null;
return x;
}
put(E e)
public void put(E e) throws InterruptedException {
if (e == null) throw new NullPointerException();
int c = -1;
Node<E> node = new Node<E>(e);
final ReentrantLock putLock = this.putLock;
final AtomicInteger count = this.count;
putLock.lockInterruptibly();
try {
//如果队列中数量已满则挂起在notFull等待队列
while (count.get() == capacity) {
notFull.await();
}
//队列总添加节点
enqueue(node);
//c为队列数增加前的值
c = count.getAndIncrement();
//ArrayBlockingQueue中唤醒的notEmpty,此处唤醒notFull等待的线程,因为ArrayBlockingQueue入队出队共用一个锁。
//也就是存在挂起在notFull的线程就一直添加节点
if (c + 1 < capacity)
notFull.signal();
} finally {
putLock.unlock();
}
//如果队列从空变为1则唤醒notEmpty中等待的线程
if (c == 0)
signalNotEmpty();
}
take()
public E take() throws InterruptedException {
E x;
int c = -1;
final AtomicInteger count = this.count;
final ReentrantLock takeLock = this.takeLock;
takeLock.lockInterruptibly();
try {
//如果队列为空,则线程等待在notEmpty队列中
while (count.get() == 0) {
notEmpty.await();
}
//出队
x = dequeue();
c = count.getAndDecrement();
//如果队列中有值且notEmpty中有线程阻塞,则一直出队
if (c > 1)
notEmpty.signal();
} finally {
takeLock.unlock();
}
//如果队列从满变为不满,则唤醒在notFull等待的线程
if (c == capacity)
signalNotFull();
return x;
}
SynchronousQueue同步队列
无缓冲阻塞队列,该队列不存储元素,每个插入操作必须等待另一个线程调用移除操作,提供FIFO和LIFO两种模式,使用自旋+CAS来控制。
成员变量
//cpu数
static final int NCPUS = Runtime.getRuntime().availableProcessors();
//如果指定的timeout的自旋次数
static final int maxTimedSpins = (NCPUS < 2) ? 0 : 32;
//未指定timeout的自旋次数
static final int maxUntimedSpins = maxTimedSpins * 16;
//指定timeout,自旋后剩余时间大于1000纳秒就挂起对应时间
static final long spinForTimeoutThreshold = 1000L;
//传输器
private transient volatile Transferer<E> transferer;
//同步操作使用可重入锁
private ReentrantLock qlock;
private WaitQueue waitingProducers;
private WaitQueue waitingConsumers;
构造方法
//默认采用LIFO模式
public SynchronousQueue() {
this(false);
}
//指定队列是先进先出还是后进先出
public SynchronousQueue(boolean fair) {
transferer = fair ? new TransferQueue<E>() : new TransferStack<E>();
}
内部类
Transferer
/**
*@e:为空时表示需要消费数据(take),不为空表示生产数据(put)
*@timed:是否超时
*@nanos:超时时间,纳秒
*/
abstract static class Transferer<E> {
abstract E transfer(E e, boolean timed, long nanos);
}
TransferStack
栈传输器
static final class TransferStack<E> extends Transferer<E> {
//节点状态:消费者
static final int REQUEST = 0;
//生产者
static final int DATA = 1;
//正在互补匹配中
static final int FULFILLING = 2;
//栈的头结点
volatile SNode head;
static final class SNode {
volatile SNode next; // 栈中下一个节点
volatile SNode match; // 匹配,判断是否取消
volatile Thread waiter; // 等待的线程
Object item; // 数据
int mode; // 节点类型
}
}
TransferQueue
队列传输器
static final class TransferQueue<E> extends Transferer<E> {
//队列头结点
transient volatile QNode head;
//队列尾节点
transient volatile QNode tail;
//队列中节点
static final class QNode {
volatile QNode next; // 下一个节点
volatile Object item; // 节点数据
volatile Thread waiter; // 等待线程
final boolean isData; // 是否为数据节点
}
}
重要方法
put(E e)
入队
public void put(E e) throws InterruptedException {
if (e == null) throw new NullPointerException();
//transfer方法返回null表示超时或中断
if (transferer.transfer(e, false, 0) == null) {
Thread.interrupted();
throw new InterruptedException();
}
}
take()
出队
public E take() throws InterruptedException {
E e = transferer.transfer(null, false, 0);
if (e != null)
return e;
Thread.interrupted();
throw new InterruptedException();
}
transfer(E e, boolean timed, long nanos)
E transfer(E e, boolean timed, long nanos) {
SNode s = null; // constructed/reused as needed
//如果e为null表示为消费者否则为生产者
int mode = (e == null) ? REQUEST : DATA;
//自旋
for (;;) {
//获得栈的头结点
SNode h = head;
if (h == null || h.mode == mode) { // 头为空或为相同模式
if (timed && nanos <= 0) { // 如果超时且已到期
if (h != null && h.isCancelled()) // 如果h不为null,且h==match
casHead(h, h.next); // 取消节点出队
else
//超时返回null
return null;
} else if (casHead(h, s = snode(s, e, h, mode))) { //设置头结点为新节点
SNode m = awaitFulfill(s, timed, nanos); //阻塞当前入栈的线程并等待被匹配
if (m == s) { // m==s说明被取消了,返回null
clean(s);
return null;
}
//匹配成功, 如果头节点不为空,并且头节点的下一个节点是s
if ((h = head) != null && h.next == s)
casHead(h, s.next); // help s's fulfiller
//根据当前节点的模式判断返回值
return (E) ((mode == REQUEST) ? m.item : s.item);
}
} else if (!isFulfilling(h.mode)) { // 此处表示模式不同
if (h.isCancelled()) // 头节点已被取消
casHead(h, h.next); // pop and retry
//创建新节点并置为头节点,mode=11或10
else if (casHead(h, s=snode(s, e, h, FULFILLING|mode))) {
for (;;) { // 自旋直到匹配或线程中断
SNode m = s.next; // m is s's match
if (m == null) { // 表示栈中除了s都为空
casHead(s, null); // pop fulfill node
s = null; // use new node next time
break; // restart main loop
}
SNode mn = m.next;
//将s设置为m的match,唤醒m处等待线程
if (m.tryMatch(s)) {
casHead(s, mn); // s,m都出栈
//根据模式返回值
return (E) ((mode == REQUEST) ? m.item : s.item);
} else // lost match
s.casNext(m, mn); // help unlink
}
}
} else { // 头结点正在匹配中
SNode m = h.next; // m is h's match
if (m == null) // waiter is gone
casHead(h, null); // pop fulfilling node
else {
SNode mn = m.next;
if (m.tryMatch(h)) // 帮助尝试匹配
casHead(h, mn); // pop both h and m
else // lost match
h.casNext(m, mn); // help unlink
}
}
}
}
PriorityBlockingQueue优先队列
一个支持优先级的无界阻塞队列,但不能保证同优先级元素的顺序,底层采用二叉堆(数组,小顶堆)实现,使用可重入锁来控制入队出队。(如果不加比较器添加的元素必须继承Comparable接口)
成员变量
//默认容量
private static final int DEFAULT_INITIAL_CAPACITY = 11;
//最大容量
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
//堆
private transient Object[] queue;
//堆大小
private transient int size;
//比较器
private transient Comparator<? super E> comparator;
//控制同步的锁
private final ReentrantLock lock;
//在为空时等待的监视器
private final Condition notEmpty;
//扩容时使用的自旋锁,通过CAS获取
private transient volatile int allocationSpinLock;
//非阻塞优先队列,用于序列化和反序列化
private PriorityQueue<E> q;
构造方法
//默认初始容量为11,比较器为null
public PriorityBlockingQueue() {
this(DEFAULT_INITIAL_CAPACITY, null);
}
//指定初始大小和比较器
public PriorityBlockingQueue(int initialCapacity,
Comparator<? super E> comparator) {
if (initialCapacity < 1)
throw new IllegalArgumentException();
//初始锁和监视器
this.lock = new ReentrantLock();
this.notEmpty = lock.newCondition();
this.comparator = comparator;
this.queue = new Object[initialCapacity];
}
重要方法
tryGrow(Object[] array, int oldCap)
对数组扩容,小于64扩容2倍+2,大于扩容1.5倍
private void tryGrow(Object[] array, int oldCap) {
lock.unlock(); // 先释放offer中的重入锁
Object[] newArray = null;
//当allocationSpinLock为0且CAS修改其为1成功
if (allocationSpinLock == 0 &&
UNSAFE.compareAndSwapInt(this, allocationSpinLockOffset,
0, 1)) {
try {
//如果旧容量小于64则扩容为old*2+2,否则扩容为1.5old
int newCap = oldCap + ((oldCap < 64) ?
(oldCap + 2) : // grow faster if small
(oldCap >> 1));
if (newCap - MAX_ARRAY_SIZE > 0) { // 如果超出最大容量限制则为Integer.MAX_VALUE-8
int minCap = oldCap + 1;
if (minCap < 0 || minCap > MAX_ARRAY_SIZE)
throw new OutOfMemoryError();
newCap = MAX_ARRAY_SIZE;
}
if (newCap > oldCap && queue == array)
newArray = new Object[newCap];
} finally {
allocationSpinLock = 0;
}
}
if (newArray == null) // 如果另外一个线程正在扩容,让出CPU控制权
Thread.yield();
lock.lock();
//如果扩容了则将旧数组中的值复制到新数组上,queue == array避免多个线程复制旧数据
if (newArray != null && queue == array) {
queue = newArray;
System.arraycopy(array, 0, newArray, 0, oldCap);
}
}
offer(E e)
public void put(E e) {
offer(e); //因为是无界的所以添加不阻塞
}
public boolean offer(E e) {
if (e == null)
throw new NullPointerException();
final ReentrantLock lock = this.lock;
lock.lock();
int n, cap;
Object[] array;
//如果当前节点数大于容量则扩容
while ((n = size) >= (cap = (array = queue).length))
tryGrow(array, cap);
try {
Comparator<? super E> cmp = comparator;
if (cmp == null)
siftUpComparable(n, e, array);
else
siftUpUsingComparator(n, e, array, cmp);
size = n + 1;
//唤醒在队列为空等待的线程
notEmpty.signal();
} finally {
lock.unlock();
}
return true;
}
siftUpComparable(int k, T x, Object[] array)
当没有比较器时,根据元素自身Comparable来插入堆中
private static <T> void siftUpComparable(int k, T x, Object[] array) {
Comparable<? super T> key = (Comparable<? super T>) x;
while (k > 0) {
//父节点位置
int parent = (k - 1) >>> 1;
Object e = array[parent];
//如果如队数比父节点大则不用调整
if (key.compareTo((T) e) >= 0)
break;
//否则调整堆
array[k] = e;
k = parent;
}
array[k] = key;
}
take()
元素出队
public E take() throws InterruptedException {
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
E result;
try {
//如果队列为空线程阻塞
while ( (result = dequeue()) == null)
notEmpty.await();
} finally {
lock.unlock();
}
return result;
}
private E dequeue() {
//元素出队位置
int n = size - 1;
//如果队列为空
if (n < 0)
return null;
else {
Object[] array = queue;
//堆顶元素出队
E result = (E) array[0];
//获得堆尾元素
E x = (E) array[n];
array[n] = null;
Comparator<? super E> cmp = comparator;
//堆顶出队后调整堆
if (cmp == null)
siftDownComparable(0, x, array, n);
else
siftDownUsingComparator(0, x, array, n, cmp);
size = n;
return result;
}
}
DelayQueue延迟队列
DelayQueue 是一个支持延时获取元素的阻塞队列,内部采用PriorityQueue存储元素,持有的元素必须继承Delay接口,在创建元素时可以指定多久才从队列中获得。
Delay接口
public interface Delayed extends Comparable<Delayed> {
//在给定的时间单位中返回与此对象相关联的剩余延迟
long getDelay(TimeUnit unit);
}
重要方法
offer(E e)
入队
public boolean offer(E e) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
q.offer(e);
//如果当前元素加入队列后在优先队列的头部
if (q.peek() == e) {
leader = null;
//唤醒在空等待或在时延等待的线程
available.signal();
}
return true;
} finally {
lock.unlock();
}
}
take()
public E take() throws InterruptedException {
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
for (;;) {
E first = q.peek();
//如果队列为空则阻塞
if (first == null)
available.await();
else {
long delay = first.getDelay(NANOSECONDS);
if (delay <= 0)
return q.poll();
first = null; // 如果队列头任然存在时延则阻塞
//已有线程阻塞
if (leader != null)
available.await();
else {
//阻塞当前线程指定delay时间
Thread thisThread = Thread.currentThread();
leader = thisThread;
try {
available.awaitNanos(delay);
} finally {
if (leader == thisThread)
leader = null;
}
}
}
}
} finally {
if (leader == null && q.peek() != null)
available.signal();
lock.unlock();
}
}
ThreadFactory
ThreadFactory接口
线程工厂接口,提供获得线程的方法
public interface ThreadFactory {
//工厂中获得线程的方法
Thread newThread(Runnable r);
}
Executors中的默认工厂
Executors中的内部类
static class DefaultThreadFactory implements ThreadFactory {
//区分不同线程工厂创建的线程
private static final AtomicInteger poolNumber = new AtomicInteger(1);
//线程组
private final ThreadGroup group;
//线程数量
private final AtomicInteger threadNumber = new AtomicInteger(1);
//线程名前缀
private final String namePrefix;
DefaultThreadFactory() {
SecurityManager s = System.getSecurityManager();
//设置工厂线程组
group = (s != null) ? s.getThreadGroup() :
Thread.currentThread().getThreadGroup();
//线程名前缀,区分多个工厂生成的线程
namePrefix = "pool-" +
poolNumber.getAndIncrement() +
"-thread-";
}
public Thread newThread(Runnable r) {
//创建线程,赋予线程工厂的线程组,name=前缀+工厂中当前线程数
Thread t = new Thread(group, r,
namePrefix + threadNumber.getAndIncrement(),
0);
if (t.isDaemon())
t.setDaemon(false);
if (t.getPriority() != Thread.NORM_PRIORITY)
t.setPriority(Thread.NORM_PRIORITY);
return t;
}
}
RejectedExecutionHandler
拒绝策略接口
无法执行的任务的处理程序
public interface RejectedExecutionHandler {
//当executor无法执行任务时可能调用的方法
void rejectedExecution(Runnable r, ThreadPoolExecutor executor);
}
AbortPolicy
ThreadPoolExecutor内部类,丢弃新任务,并抛出 RejectedExecutionException异常
public static class AbortPolicy implements RejectedExecutionHandler {
public AbortPolicy() { }
//丢弃任务,抛出异常信息:Task+任务toString+ rejected from +线程池toString(任务被线程池拒绝)
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
throw new RejectedExecutionException("Task " + r.toString() +
" rejected from " +
e.toString());
}
}
DiscardPolicy
ThreadPoolExecutor内部类,不做任何操作,直接丢弃新任务
public static class DiscardPolicy implements RejectedExecutionHandler {
public DiscardPolicy() { }
//不做任何操作
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
}
}
DiscardOldestPolicy
ThreadPoolExecutor内部类,丢弃队列队首的元素,并执行新任务
public static class DiscardOldestPolicy implements RejectedExecutionHandler {
public DiscardOldestPolicy() { }
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
//如果线程池未关闭
if (!e.isShutdown()) {
//当前阻塞队列队首出队
e.getQueue().poll();
//执行新任务
e.execute(r);
}
}
}
CallerRunsPolicy
ThreadPoolExecutor内部类,由调用线程执行新任务
public static class CallerRunsPolicy implements RejectedExecutionHandler {
public CallerRunsPolicy() { }
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
//如果线程池未关闭
if (!e.isShutdown()) {
//由当前线程执行任务的run方法
r.run();
}
}
}