【java】BlockingQueue解析【硬】

什么是BlockingQueue

BlockingQueue即阻塞队列,它算是一种将ReentrantLock用得非常精彩的一种方式,很好的解决了多线程中,如何高效安全“传输”数据的问题。依据它的基本原理,我们可以实现Web中的长连接聊天功能,当然其最常用的还是用于实现生产者与消费者模式。

【java】BlockingQueue解析【硬】_第1张图片

Java中BlockingQueue源码
public interface BlockingQueue<E> extends Queue<E> {
	//将给定元素设置到队列中,如果设置成功返回true, 
	//否则返回false。如果是往限定了长度的队列中设置值,
	//推荐使用offer()方法。
    boolean add(E var1);
	//将给定的元素设置到队列中,如果设置成功返回true, 否则返回false. 
	//e的值不能为空,否则抛出空指针异常。
    boolean offer(E var1);
	//将元素设置到队列中,如果队列中没有多余的空间,
	//该方法会一直阻塞,直到队列中有多余的空间
    void put(E var1) throws InterruptedException;
	//将给定元素在给定的时间内设置到队列中,
	//如果设置成功返回true, 否则返回false.时间单位不能为空
    boolean offer(E var1, long var2, TimeUnit var4) throws InterruptedException;
	//从队列中获取值,如果队列中没有值,线程会一直阻塞,
	//直到队列中有值,并且该方法取得了该值。
    E take() throws InterruptedException;
	//在给定的时间里,从队列中获取值,时间到了直接调用普通的poll方法,
	//为null则直接返回null
    E poll(long var1, TimeUnit var3) throws InterruptedException;
    //获取队列中剩余的空间。
    int remainingCapacity();
	//从队列中移除指定的值。
    boolean remove(Object var1);
	//判断队列中是否拥有该值。
    boolean contains(Object var1);
	//将队列中值,全部移除,并发设置到给定的集合中。
    int drainTo(Collection<? super E> var1);
	//指定最多数量限制将队列中值,全部移除,并发设置到给定的集合中。
    int drainTo(Collection<? super E> var1, int var2);
}

在下面展开之前,读者可以自行了解下ReentrantLock(可重入锁)和Condition(锁条件类)的一些内容,可以参考博文进入

Java中BlockingQueue的实现

在Java中,BlockingQueue是一个接口,它的实现类有ArrayBlockingQueue、DelayQueue、 LinkedBlockingDeque、LinkedBlockingQueue、PriorityBlockingQueue、SynchronousQueue等,它们的区别主要体现在存储结构上或对元素操作上的不同,但是对于take与put操作的原理,却是类似的。
【java】BlockingQueue解析【硬】_第2张图片

简单说明:

1
ArrayBlockingQueue是基于数组实现的阻塞队列,需自定义数组长度,此队列按照FIFO(先进先出)原则进行元素排序,支持公平和非公平锁。【注:每一个线程在获取锁的时候可能都会排队等待,如果在等待时间上,先获取锁的线程的请求一定先被满足,那么这个锁就是公平的。反之,这个锁就是不公平的。公平的获取锁,也就是当前等待时间最长的线程先获取锁】
2
LinkedBlockingQueue:一个由链表结构组成的有界队列,此队列的长度为Integer.MAX_VALUE。此队列按照先进先出的顺序进行排序。
3
PriorityBlockingQueue: 一个支持线程优先级排序的无界队列,默认自然序进行排序,也可以自定义实现compareTo()方法来指定元素排序规则,不能保证同优先级元素的顺序。
4
DelayQueue: 一个实现PriorityBlockingQueue实现延迟获取的无界队列,在创建元素时,可以指定多久才能从队列中获取当前元素。只有延时期满后才能从队列中获取元素。
DelayQueue可以运用在以下应用场景:
1.缓存系统的设计:可以用DelayQueue保存缓存元素的有效期,使用一个线程循环查询DelayQueue,一旦能从DelayQueue中获取元素时,表示缓存有效期到了。
2.定时任务调度。使用DelayQueue保存当天将会执行的任务和执行时间,一旦从DelayQueue中获取到任务就开始执行,从比如TimerQueue就是使用DelayQueue实现的。
5.
SynchronousQueue: 一个不存储元素的阻塞队列,每一个put操作必须等待take操作,也就是某个时刻只能允许一个元素在队列中,也只允许某时刻仅有一个元素被取出。支持公平锁和非公平锁。SynchronousQueue的一个使用场景是在线程池里。Executors.newCachedThreadPool()就使用了SynchronousQueue,这个线程池根据需要(新任务到来时)创建新的线程,如果有空闲线程则会重复使用,线程空闲了60秒后会被回收。
6
LinkedTransferQueue: 一个由链表结构组成的无界阻塞队列,相当于其它队列,LinkedTransferQueue队列多了transfer和tryTransfer方法。
7
LinkedBlockingDeque: 一个由链表结构组成的双向阻塞队列。队列头部和尾部都可以添加和移除元素,多线程并发时,可以将锁的竞争最多降到一半。

经常用的是ArrayBlockingQueue、LinkedBlockingQueue和DelayQueue,以下进行较详细的介绍。

ArrayBlockingQueue
1 源码
	final Object[] items;//存储队列元素的数组
    int takeIndex;//拿数据的索引,用于take,poll,peek,remove方法
    int putIndex;//存数据的索引,用于put,offer,add方法
    int count;//记录元素个数
    final ReentrantLock lock;//可重入锁
    private final Condition notEmpty;//非空条件,由Lock创建
    private final Condition notFull;//非满条件,由Lock创建
    transient ArrayBlockingQueue<E>.Itrs itrs;//迭代对象
	//大于目标值置0
    static final int inc(int i, int modulus) {
        ++i;
        if (i >= modulus) {
            i = 0;
        }

        return i;
    }
	//小于0,记为目标值-1
    static final int dec(int i, int modulus) {
        --i;
        if (i < 0) {
            i = modulus - 1;
        }

        return i;
    }
	//找到索引为i的值
    final E itemAt(int i) {
        return this.items[i];
    }
	//找到索引为i的值
    static <E> E itemAt(Object[] items, int i) {
        return items[i];
    }
	//入队
    private void enqueue(E e) {
        Object[] items = this.items;
        items[this.putIndex] = e;
        if (++this.putIndex == items.length) {
            this.putIndex = 0;
        }

        ++this.count;
        this.notEmpty.signal();//非空信号激活
    }
	//出队
    private E dequeue() {
        Object[] items = this.items;
        E e = items[this.takeIndex];
        items[this.takeIndex] = null;
        if (++this.takeIndex == items.length) {
            this.takeIndex = 0;
        }

        --this.count;
        if (this.itrs != null) {
            this.itrs.elementDequeued();
        }

        this.notFull.signal();//非满信号激活
        return e;
    }
	//删除元素
    void removeAt(int removeIndex) {
        Object[] items = this.items;
        if (removeIndex == this.takeIndex) {
            items[this.takeIndex] = null;
            if (++this.takeIndex == items.length) {
                this.takeIndex = 0;
            }

            --this.count;
            if (this.itrs != null) {
                this.itrs.elementDequeued();
            }
        } else {
            int i = removeIndex;
            int putIndex = this.putIndex;

            while(true) {
                int pred = i++;
                if (i == items.length) {
                    i = 0;
                }

                if (i == putIndex) {
                    items[pred] = null;
                    this.putIndex = pred;
                    --this.count;
                    if (this.itrs != null) {
                        this.itrs.removedAt(removeIndex);
                    }
                    break;
                }

                items[pred] = items[i];
            }
        }

        this.notFull.signal();
    }
	//声明非公平锁的队列
    public ArrayBlockingQueue(int capacity) {
        this(capacity, false);
    }
	//声明非/公平锁的队列,可选
    public ArrayBlockingQueue(int capacity, boolean fair) {
        if (capacity <= 0) {
            throw new IllegalArgumentException();
        } else {
            this.items = new Object[capacity];//初始化容量
            this.lock = new ReentrantLock(fair);//初始化锁
            this.notEmpty = this.lock.newCondition();//初始化非空条件,等待
            this.notFull = this.lock.newCondition();//初始化非满等待条件
        }
    }

    public ArrayBlockingQueue(int capacity, boolean fair, Collection<? extends E> c) {
        this(capacity, fair);
        ReentrantLock lock = this.lock;
        lock.lock();

        try {
            Object[] items = this.items;
            int i = 0;

            Object e;
            try {
            //将集合添加进数组构成的队列中
                for(Iterator var7 = c.iterator(); var7.hasNext(); items[i++] = Objects.requireNonNull(e)) {
                    e = var7.next();
                }
            } catch (ArrayIndexOutOfBoundsException var12) {
                throw new IllegalArgumentException();
            }

            this.count = i;
            this.putIndex = i == capacity ? 0 : i;
        } finally {
            lock.unlock();
        }

    }

实现原理图,先进先出(FIFO),即队头出队,队尾入队,不论是add 和offer 底层调用的是 enqueue ,在正常情况下都是无阻塞的添加。【java】BlockingQueue解析【硬】_第3张图片
但是会出现一种情况,队列元素可能只进不出,也就是会一直入队元素直至填满,此时takeIndex仍在队头的位置,索引为0,而putIndex位于队尾,索引为capacity-1,这个时候,会将NotEmpty是一直打开,等待取值,而NotFull条件不进行阻塞,不能再添加数据是根据添加元素数和数组长度的关系来进行的,如果两者相等即满了,则返回false,不添加,而且将 putIndex 的索引值置0,即如果有元素出队,下次入队的位置是队头,相当于循环队列的形式,是通过调用 inc 方法实现。
同样如果是一直出队,takeIndex 索引值不断增大,直至capacity-1 ,当所有元素都出队后,这个时候需要将takeIndex和putIndex置0,NotFull条件一直打开,没有元素的时候,返回是null。

一直入队:
【java】BlockingQueue解析【硬】_第4张图片
入队源码

 private void enqueue(E e) {
        Object[] items = this.items;
        items[this.putIndex] = e;
        //满的时候,置0
        if (++this.putIndex == items.length) {
            this.putIndex = 0;
        }

        ++this.count;
        this.notEmpty.signal();
    }
// offer add底层调用的是 offer
 public boolean offer(E e) {
        Objects.requireNonNull(e);
        ReentrantLock lock = this.lock;
        lock.lock();

        boolean var3;
        try {
            if (this.count == this.items.length) {
                var3 = false;
                return var3;
            }

            this.enqueue(e);
            var3 = true;
        } finally {
            lock.unlock();
        }

        return var3;
    }
put方法,阻塞添加
1 原理和源码

put方法是一个阻塞的方法,如果队列元素已满,那么当前线程将会被notFull条件对象挂起加到等待队列中,直到队列有空档才会唤醒执行添加操作。但如果队列没有满,那么就直接调用enqueue(e)方法将元素加入到数组队列中。
说白了就是当队列满时通过条件对象Condtion来阻塞当前调用put方法的线程,直到线程又再次被唤醒执行。总得来说添加线程的执行存在以下两种情况,一是,队列已满,那么新到来的put线程将添加到notFull的条件队列中等待,二是,有移除线程执行移除操作,移除成功同时唤醒put线程。

public void put(E e) throws InterruptedException {
        Objects.requireNonNull(e);
        ReentrantLock lock = this.lock;
        lock.lockInterruptibly();
        try {
            while(this.count == this.items.length) {
                this.notFull.await();
            }
            this.enqueue(e);
        } finally {
            lock.unlock();
        }

    }
移除原理

poll 方法,该方法获取并移除此队列的头元素,若队列为空,则返回 null

public E poll() {
        ReentrantLock lock = this.lock;
        lock.lock();

        Object var2;
        try {
            var2 = this.count == 0 ? null : this.dequeue();
        } finally {
            lock.unlock();
        }

        return var2;
    }
 //删除队列头元素并返回
 private E dequeue() {
        Object[] items = this.items;
        E e = items[this.takeIndex];
        items[this.takeIndex] = null;
        //takeIndex索引加1并判断是否与数组长度相等,
      //如果相等说明已到尽头,恢复为0
        if (++this.takeIndex == items.length) {
            this.takeIndex = 0;
        }
        --this.count;
        if (this.itrs != null) {
            this.itrs.elementDequeued();//同时更新迭代器中的元素数据
        }
        this.notFull.signal();
        return e;
    }
remove(Object o)方法

remove(Object
o)方法的删除过程相对复杂些,因为该方法并不是直接从队列头部删除元素。首先线程先获取锁,再一步判断队列count>0,这点是保证并发情况下删除操作安全执行。接着获取下一个要添加源的索引putIndex以及takeIndex索引,作为后续循环的结束判断,因为只要putIndex与takeIndex不相等就说明队列没有结束。然后通过while循环找到要删除的元素索引,执行removeAt(i)方法删除,在removeAt(i)方法中实际上做了两件事,一是首先判断队列头部元素是否为删除元素,如果是直接删除,并唤醒添加线程,二是如果要删除的元素并不是队列头元素,那么执行循环操作,从要删除元素的索引removeIndex之后的元素都往前移动一个位置,那么要删除的元素就被removeIndex之后的元素替换,从而也就完成了删除操作。

public boolean remove(Object o) {
        if (o == null) {
            return false;
        } else {
        	//获取锁
            ReentrantLock lock = this.lock;
            lock.lock();

            try {
            	//如果存在元素
                if (this.count > 0) {
                	//获得前后索引位置
                    Object[] items = this.items;
                    int i = this.takeIndex;
                    int end = this.putIndex;
                    int to = i < end ? end : items.length;
                    label96:
                    while(true) {
                        while(i >= to) {//遍历完所有元素了
                            if (to == end) {
                                break label96;
                            }

                            i = 0;
                            to = end;
                        }
						//如果找到,删除,返回true
                        if (o.equals(items[i])) {
                            this.removeAt(i);
                            boolean var7 = true;
                            return var7;
                        }
                        ++i;
                    }
                }
				//没找到 返回 false
                boolean var11 = false;
                return var11;
            } finally {
                lock.unlock();
            }
        }
    }
//如果要删除的元素不在队列头部,
//那么只需循环迭代把删除元素后面的所有元素往前移动一个位置
//获取下一个要被添加的元素的索引,作为循环判断结束条件
void removeAt(int removeIndex) {
        Object[] items = this.items;
        if (removeIndex == this.takeIndex) {
            items[this.takeIndex] = null;
            if (++this.takeIndex == items.length) {
                this.takeIndex = 0;
            }
            --this.count;
            if (this.itrs != null) {
                this.itrs.elementDequeued();
            }
        } else {
        //如果想删除的元素在中间
            int i = removeIndex;
            int putIndex = this.putIndex;

            while(true) {
                int pred = i++;
                if (i == items.length) {
                    i = 0;
                }
                if (i == putIndex) {
                    items[pred] = null;
                    this.putIndex = pred;
                    --this.count;
                    if (this.itrs != null) {
                        this.itrs.removedAt(removeIndex);
                    }
                    break;
                }
                items[pred] = items[i];//把后一个元素前移覆盖要删除的元
            }
        }

        this.notFull.signal();
    }

take()方法

take方法其实很简单,有就删除没有就阻塞,注意这个阻塞是可以中断的,如果队列没有数据那么就加入notEmpty条件队列等待(有数据就直接取走,方法结束),如果有新的put线程添加了数据,那么put操作将会唤醒take线程,执行take操作。

源码
 //从队列头部删除,队列没有元素就阻塞,可中断
public E take() throws InterruptedException {
        ReentrantLock lock = this.lock;
        lock.lockInterruptibly();

        Object var2;
        try {
            while(this.count == 0) {
                this.notEmpty.await();
            }

            var2 = this.dequeue();
        } finally {
            lock.unlock();
        }

        return var2;
    }
peek方法

直接返回当前队列的头元素但不删除任何元素。

public E peek() {
        ReentrantLock lock = this.lock;
        lock.lock();

        Object var2;
        try {
            var2 = this.itemAt(this.takeIndex);
        } finally {
            lock.unlock();
        }

        return var2;
    }
代码实例
public class BlockQueue {
    public static void main(String[] args){
        BlockingQueue bq=new ArrayBlockingQueue(2);
        Producer p=new Producer("Pro",bq);
        Customer c=new Customer("Cro",bq);
        p.start();
        c.start();
    }
}

class Producer extends Thread{
    private BlockingQueue bq;
    public Producer(String name,BlockingQueue bq){
        super(name);
        this.bq=bq;
    }
    public void run(){
        String[] args={"Spring","Summer","Fall","Winter"};

        for(int i=0;i<100;i++){
            System.out.println("生成集合元素...");
            try {
                bq.put(args[i%4]);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("完成生成集合元素...");
    }
}
class Customer extends Thread{
    private BlockingQueue bq;
    public Customer(String name,BlockingQueue bq){
        super(name);
        this.bq=bq;
    }
    public void run(){
        System.out.println("消费集合元素...");
        while(true){
            try {
                System.out.println("集合元素消费结束..."+bq.take());
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
          //  System.out.println("集合元素消费结束..."+bq);
        }
    }

指定阻塞队列为2,生产者消费者谁先抢到线程就先执行呢个,但是一定是先生成才能消费元素
【java】BlockingQueue解析【硬】_第5张图片

DelayQueue

DelayQueue的泛型参数需要实现Delayed接口,Delayed接口继承了Comparable接口,DelayQueue内部使用非线程安全的优先队列(PriorityQueue),并使用Leader/Followers模式,最小化不必要的等待时间。DelayQueue不允许包含null元素。

Leader/Followers模式:

1 有若干个线程(一般组成线程池)用来处理大量的事件
2 有一个线程作为领导者,等待事件的发生;其他的线程作为追随者,仅仅是睡眠。
3 假如有事件需要处理,领导者会从追随者中指定一个新的领导者,自己去处理事件。
4 唤醒的追随者作为新的领导者等待事件的发生。
5 处理事件的线程处理完毕以后,就会成为追随者的一员,直到被唤醒成为领导者。
6 假如需要处理的事件太多,而线程数量不够(能够动态创建线程处理另当别论),则有的事件可能会得不到处理
综上:
所有线程会有三种身份中的一种:leader和follower,以及一个干活中的状态:proccesser。它的基本原则就是,永远最多只有一个leader。而所有follower都在等待成为leader。线程池启动时会自动产生一个Leader负责等待网络IO事件,当有一个事件产生时,Leader线程首先通知一个Follower线程将其提拔为新的Leader,然后自己就去干活了,去处理这个网络事件,处理完毕后加入Follower线程等待队列,等待下次成为Leader。这种方法可以增强CPU高速缓存相似性,及消除动态内存分配和线程间的数据交换。

源码
private final transient ReentrantLock lock = new ReentrantLock();
    private final PriorityQueue<E> q = new PriorityQueue();
    //用于优化阻塞通知的线程元素leader,Leader/Followers模式
    private Thread leader; 
    private final Condition available;

    public DelayQueue() {
        this.available = this.lock.newCondition();
    }

    public DelayQueue(Collection<? extends E> c) {
        this.available = this.lock.newCondition();
        this.addAll(c);
    }
offer方法
public boolean offer(E e) {
        ReentrantLock lock = this.lock;
        lock.lock();
        boolean var3;
        try {
            this.q.offer(e);
            // 如果原来队列为空,重置leader线程,通知available条件
            if (this.q.peek() == e) {
                this.leader = null;
                this.available.signal();
            }
            var3 = true;
        } finally {
            lock.unlock();
        }

        return var3;
    }
//因为DelayQueue不限制长度,因此添加元素的时候不会因为队列已满产生阻塞,
//因此带有超时的offer方法的超时设置是不起作用的
public boolean offer(E e, long timeout, TimeUnit unit) {
        return this.offer(e);
    }

poll()

普通的poll()方法:如果延迟时间没有耗尽的话,直接返回null

源码
public E poll() {
        ReentrantLock lock = this.lock;
        lock.lock();

        Delayed var3;
        try {
            E first = (Delayed)this.q.peek();
            //延迟时间耗尽,则元素出队,否则为null
            var3 = first != null && first.getDelay(TimeUnit.NANOSECONDS) <= 0L ? (Delayed)this.q.poll() : null;
        } finally {
            lock.unlock();
        }

        return var3;
    }
take()方法
源码
public E take() throws InterruptedException {
        ReentrantLock lock = this.lock;
        lock.lockInterruptibly();
        try {
            while(true) {
                while(true) {
                    E first = (Delayed)this.q.peek();
                    //如果队列不为空
                    if (first != null) {
                    //设置延时
                        long delay = first.getDelay(TimeUnit.NANOSECONDS);
                        //延时耗尽 出队元素
                        if (delay <= 0L) {
                            Delayed var14 = (Delayed)this.q.poll();
                            return var14;
                        }
						//重置 first
                        first = null;
                        //leader不为空,则有线程在执行
                        //available阻塞
                        if (this.leader != null) {
                            this.available.await();
                        } else {
                        //没有 leader 则本线程为leader
                            Thread thisThread = Thread.currentThread();
                            this.leader = thisThread;

                            try {
                            // 尝试等待直到延迟时间耗尽
                                this.available.awaitNanos(delay);
                            } finally {
                            //重置 leader
                                if (this.leader == thisThread) {
                                    this.leader = null;
                                }

                            }
                        }
                    } else {
                    //first为空则等待
                        this.available.await();
                    }
                }
            }
        } finally {
        //没有leader程序且队列不为空 则通知线程执行
            if (this.leader == null && this.q.peek() != null) {
                this.available.signal();
            }
            lock.unlock();
        }
    }

带有延迟的poll
public E poll(long timeout, TimeUnit unit) throws InterruptedException {
        long nanos = unit.toNanos(timeout);
        ReentrantLock lock = this.lock;
        lock.lockInterruptibly();

        try {
            while(true) {
                E first = (Delayed)this.q.peek();
                if (first != null) {
                    long delay = first.getDelay(TimeUnit.NANOSECONDS);
                    if (delay <= 0L) {
                        Delayed var21 = (Delayed)this.q.poll();
                        return var21;
                    }

                    Thread thisThread;
                    if (nanos <= 0L) {
                        thisThread = null;
                        return thisThread;
                    }

                    first = null;
                    // 当leader线程不为空时(此时delay>=nanos),等待的时间
                    // 似乎delay更合理,但是nanos也可以,因为排在当前线程前面的
                    // 其他线程返回时会唤醒available条件从而返回,
                    if (nanos >= delay && this.leader == null) {
                        thisThread = Thread.currentThread();
                        this.leader = thisThread;

                        try {
                            long timeLeft = this.available.awaitNanos(delay);
                            nanos -= delay - timeLeft;
                        } finally {
                            if (this.leader == thisThread) {
                                this.leader = null;
                            }

                        }
                    } else {
                        nanos = this.available.awaitNanos(nanos);
                    }
                } else {
                    if (nanos <= 0L) {
                        Object var8 = null;
                        return (Delayed)var8;
                    }

                    nanos = this.available.awaitNanos(nanos);
                }
            }
        } finally {
            if (this.leader == null && this.q.peek() != null) {
                this.available.signal();
            }

            lock.unlock();
        }
    }
LinkedBlockingQueue,和ArrayBlockingQueue类似
	private final int capacity;
    private final AtomicInteger count;//记录数目
    transient LinkedBlockingQueue.Node<E> head;
    private transient LinkedBlockingQueue.Node<E> last;
    private final ReentrantLock takeLock;//取锁
    private final Condition notEmpty;//不为空锁
    private final ReentrantLock putLock;//存放值锁
    private final Condition notFull;//非满锁
 	public LinkedBlockingQueue() {
        this(2147483647);
    }
    public LinkedBlockingQueue(int capacity) {
        this.count = new AtomicInteger();
        this.takeLock = new ReentrantLock();
        this.notEmpty = this.takeLock.newCondition();
        this.putLock = new ReentrantLock();
        this.notFull = this.putLock.newCondition();
        if (capacity <= 0) {
            throw new IllegalArgumentException();
        } else {
            this.capacity = capacity;
            this.last = this.head = new LinkedBlockingQueue.Node((Object)null);
        }
    }
线程池中使用了阻塞队列
ThreadPoolExecutor 线程池源码
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) {
        this.ctl = new AtomicInteger(ctlOf(-536870912, 0));
        this.mainLock = new ReentrantLock();
        this.workers = new HashSet();
        this.termination = this.mainLock.newCondition();
        if (corePoolSize >= 0 && maximumPoolSize > 0 && maximumPoolSize >= corePoolSize && keepAliveTime >= 0L) {
            if (workQueue != null && threadFactory != null && handler != null) {
                this.corePoolSize = corePoolSize;
                this.maximumPoolSize = maximumPoolSize;
                this.workQueue = workQueue;
                this.keepAliveTime = unit.toNanos(keepAliveTime);
                this.threadFactory = threadFactory;
                this.handler = handler;
            } else {
                throw new NullPointerException();
            }
        } else {
            throw new IllegalArgumentException();
        }
    }

TimeUnit:时间单位;
BlockingQueue:等待的线程存放队列;
keepAliveTime:非核心线程的闲置超时时间,超过这个时间就会被回收;
RejectedExecutionHandler:线程池对拒绝任务的处理策略。
自定义线程池:这个构造方法对于队列是什么类型比较关键。
在使用有界队列时,若有新的任务需要执行,如果线程池实际线程数小于corePoolSize,则优先创建线程,
若大于corePoolSize,则会将任务加入队列,
若队列已满,则在总线程数不大于maximumPoolSize的前提下,创建新的线程,
若队列已经满了且线程数大于maximumPoolSize,则执行拒绝策略。或其他自定义方式。

具体执行源码
public void execute(Runnable command) {
//指令为null抛异常
        if (command == null) {
            throw new NullPointerException();
        } else {
            //线程池实际线程数小于corePoolSize,则优先创建线程,
            int c = this.ctl.get();//实际线程数
            if (workerCountOf(c) < this.corePoolSize) {
                if (this.addWorker(command, true)) {
                    return;
                }

                c = this.ctl.get();
            }
			//线程池中实际线程小于0,而命令放入队列中
            if (isRunning(c) && this.workQueue.offer(command)) {
                int recheck = this.ctl.get();//重复检查
                //线程池中实际线程大于等于0,命令被移除
                if (!isRunning(recheck) && this.remove(command)) {
                    this.reject(command);
                } else if (workerCountOf(recheck) == 0) {
                    this.addWorker((Runnable)null, false);
                }
            } else if (!this.addWorker(command, false)) {
                this.reject(command);
            }

        }
    }

【参考】进入

你可能感兴趣的:(Java基础)