线程池的阻塞队列BlockingQueue 以及拒绝策略RejectedExecutionHandler

阻塞队列

BlockingQueue的实现类有:

  • ArrayBlockingQueue(有界队列):使用该对象时,若有新任务需要执行,如果线程池的实际线程数少于corePoolSize,则会优先创建新的线程,若大于,则会将新任务加入到等待队列。当队列满时,则在总线程数不大于maximumPoolSize的前提下,创建新的线程执行任务。
  • SynchronousQueue(同步移交队列):它是一个特殊的队列,它的名字其实就蕴含了它的特征 同步的队列。为什么说是同步的呢?这里说的并不是多线程的并发问题,而是因为当一个线程往队列中写入一个元素时,写入操作不会立即返回,需要等待另一个线程来将这个元素拿走;同理,当一个读线程做读操作的时候,同样需要一个相匹配的写线程的写操作。这里的 Synchronous 指的就是读线程和写线程需要同步,一个读线程匹配一个写线程。
  • LinkedBlockingQueue(无界队列):使用该对象时,除非系统资源耗尽,否则不存在入队失败的情况。当有新任务来时,若系统的线程数量小于corePoolSize,线程池会生成新的线程执行,当线程数达到corePoolSize时就不会再继续增加了,而是将任务加入到等待队列,该队列会保持无限增长。(默认最大值,易造成OOM)
  • PriorityBlockingQueue(优先任务队列):该功能由PriorityBlockingQueue实现。该类是一个特殊的无界队列。ArrayBlockingQueue和LinkedBlockingQueue都是按照先进先出处理任务,而该类则可以根据任务自身的优先级顺序先后执行。

拒绝策略 

RejectedExecutionHandler 局决策略有:

  • AbortPolicy中止策略:该策略是默认饱和策略。使用该策略时在饱和时会抛出RejectedExecutionException(继承自RuntimeException),调用者可捕获该异常自行处理。

            /**
             * Always throws RejectedExecutionException.
             */
            public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
                throw new RejectedExecutionException("Task " + r.toString() +
                                                     " rejected from " +
                                                     e.toString());
            }
  • DiscardPolicy抛弃策略:不做任何处理直接抛弃任务

            /**
             * Does nothing, which has the effect of discarding task r.
             */
            public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            }
  • DiscardOldestPolicy:抛弃旧任务策略 先将阻塞队列中的头元素出队抛弃,再尝试提交任务。如果此时阻塞队列使用PriorityBlockingQueue优先级队列,将会导致优先级最高的任务被抛弃,因此不建议将该种策略配合优先级队列使用。

           /**
             * Obtains and ignores the next task that the executor
             * would otherwise execute, if one is immediately available,
             * and then retries execution of task r, unless the executor
             * is shut down, in which case task r is instead discarded.
             */
            public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
                if (!e.isShutdown()) {
                    e.getQueue().poll();
                    e.execute(r);
                }
            }
  • CallerRunsPolicy:调用者运行,既不抛弃任务也不抛出异常,直接运行任务的run方法,换言之将任务回退给调用者来直接运行。使用该策略时线程池饱和后将由调用线程池的主线程自己来执行任务,因此在执行任务的这段时间里主线程无法再提交新任务,从而使线程池中工作线程有时间将正在处理的任务处理完成。

            /**
             * Executes task r in the caller's thread, unless the executor
             * has been shut down, in which case the task is discarded.
             */
            public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
                if (!e.isShutdown()) {
                    r.run();
                }
            }

猜你喜欢

转载自blog.csdn.net/weixin_44912855/article/details/114872352