java阻塞队列和线程池工作队列

什么是阻塞队列,简单来讲,就是我们往队列里面添加东西时,如果满了就会执行一定的操作,比如阻塞那个加入元素的线程,而取出元素时,如果队列为空,也会执行一定的操作,比如阻塞那个取元素的线程
java中常见的几个阻塞队列

  • ArrayBlockingQueue:一个由数组结构组成的有界阻塞队列。
  • LinkedBlockingQueue:一个由链表结构组成的有界阻塞队列。
  • PriorityBlockingQueue:一个支持优先级排序的无界阻塞队列。
  • DelayQueue:一个使用优先级队列实现的无界阻塞队列。
  • SynchronousQueue:一个不存储元素的阻塞队列。
  • LinkedTransferQueue:一个由链表结构组成的无界阻塞队列。
  • LinkedBlockingDeque:一个由链表结构组成的双向阻塞队列。

这些所谓的阻塞队列,常用于生产者消费者模型,一个队列为空,消费者就会阻塞,一个队列满了,生产者就会阻塞。
在线程池中就会用于线程池中的工作队列,用于存储任务

ArrayBlockingQueue队列

这是个以数组为基础

七大参数

public ThreadPoolExecutor(
		int corePoolSize,//核心线程个数
        int maximumPoolSize,//线程池的最大线程个数
        long keepAliveTime,//线程池中非核心线程空闲的存活时间大小
        TimeUnit unit,//线程空闲存活时间单位
        BlockingQueue<Runnable> workQueue,//存放任务的阻塞队列
         ThreadFactory threadFactory,//用于设置创建线程的工厂,可以给创建的线程设置有意义的名字,可方便排查问题。
         RejectedExecutionHandler handler//拒绝策略
         ) {
         
        if (corePoolSize < 0 ||
            maximumPoolSize <= 0 ||
            maximumPoolSize < corePoolSize ||
            keepAliveTime < 0)
            throw new IllegalArgumentException();
        if (workQueue == null || threadFactory == null || handler == null)
            throw new NullPointerException();
        this.acc = System.getSecurityManager() == null ?
                null :
                AccessController.getContext();
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
    }

四大拒绝策略


当我们的工作队列满了,而线程的总个数也达到了线程的最大个数,这时候就会执行拒绝策略了,拒绝策略主要有:

  • CallerRunsPolicy
  • AbortPolicy
  • DiscardPolicy
  • DiscardOldestPolicy
CallerRunsPolicy
public static class CallerRunsPolicy implements RejectedExecutionHandler {
        public CallerRunsPolicy() { }    
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        	//只要这个线程池没有关掉,那么就可以接受这个线程云心
            if (!e.isShutdown()) {
            	//注意了,这里要分清楚连个所谓的“线程”,一个是本身线程池的线程,一个是传过来的Runable
                r.run();
            }
        }
    }

这里要区分run和start,我们需要注意这里有两种线程,一种是线程池的线程,二是由线程池调用者传过来的任务线程也就是Runnable对象,在执行这个拒绝策略的时候,是调用了Runnable的run方法,而不是start方法,所以java并没有特意为这个Runnable对象去独立一个线程出来,所以会等Runnable对象的run方法执行完,才能继续往下,而如果是start的话,调用完start就继续往下了,而不管start继续执行run有关了。所以这里变成了同步,而不是异步,没有真正开出一个线程,而仅仅是包装到调用者里面去了。
另外这个拒绝策略是没有对其这个线程,而是交给调用者的线程去执行了。

AbortPolicy
public static class AbortPolicy implements RejectedExecutionHandler {
        public AbortPolicy() { }
        //这个拒绝策略简单,直接抛弃掉,并且抛出异常
		public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            throw new RejectedExecutionException("Task " + r.toString() +
                                                 " rejected from " +
                                                 e.toString());
        }
    }
DiscardPolicy
public static class DiscardPolicy implements RejectedExecutionHandler {
        public DiscardPolicy() { }
        //这个拒绝策略没啥,比上面还简单,就直接丢弃,啥也不做,也不通知
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        }
    }
DiscardOldestPolicy
public static class DiscardOldestPolicy implements RejectedExecutionHandler {
        public DiscardOldestPolicy() { }
        //这里有点无聊
        //会丢弃线程池工作队列中最老的线程,然后将这个线程加入进去
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            if (!e.isShutdown()) {
                e.getQueue().poll();
                e.execute(r);
            }
        }
    }

常用线程池

线程池的异常处理

java线程池阻塞不拒绝 java 线程池 阻塞队列_线程池