1、在使用ThreadPoolExecutor创建多线程时候,需要出入多个参数,如下:

public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue,
                          ThreadFactory threadFactory,
                          RejectedExecutionHandler handler) {

其中的RejectedExecutionHandler handler就是指定拒绝策略,是指当任务添加到线程池中被拒绝时采取的处理措施。当任务添加到线程池中之所以被拒绝,可能是由于:线程池异常关闭或者任务数量超过线程池的最大限制。线程池共包括4种拒绝策略,它们分别是:AbortPolicyCallerRunsPolicyDiscardOldestPolicyDiscardPolicy

AbortPolicy:当任务添加到线程池中被拒绝时,它将抛出 RejectedExecutionException 异常。是线程池默认的处理策略。
CallerRunsPolicy当任务添加到线程池中被拒绝时,会在线程池当前正在运行的Thread线程池中处理被拒绝的任务。这种策略会降低对于新任务提交速度,影响程序的整体性能。另外,这个策略喜欢增加队列容量。如果您的应用程序可以承受此延迟并且你不能任务丢弃任何一个任务请求的话,你可以选择这个策略。(对比之下是最可靠的策略)。
DiscardOldestPolicy当任务添加到线程池中被拒绝时,线程池会放弃等待队列中最久的未处理任务,然后将被拒绝的任务添加到等待队列中。也即此策略将丢弃最早的未处理的任务请求。
DiscardPolicy 当任务添加到线程池中被拒绝时,线程池将丢弃被拒绝的任务。也即不处理新任务,直接丢弃掉。

2、DiscardPolicy 

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;public class DiscardPolicyDemo {private static final int THREADS_SIZE = 2;private static final int MAX_MUM_POOLSIZE = 4;private static final int CAPACITY = 2;public static void main(String[] args) throws Exception {// 创建线程池。ThreadPoolExecutor pool = new ThreadPoolExecutor(THREADS_SIZE, MAX_MUM_POOLSIZE, 0, TimeUnit.SECONDS,new ArrayBlockingQueue<Runnable>(CAPACITY));// 设置线程池的拒绝策略为"丢弃"pool.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy());// 新建10个任务,并将它们添加到线程池中。for (int i = 0; i < 10; i++) {Runnable myrun = new MyRunnable("task-"+i);pool.execute(myrun);}// 关闭线程池pool.shutdown();}
}class MyRunnable implements Runnable {private String name;public MyRunnable(String name) {this.name = name;}public void run() {try {System.out.println(this.name + " is running.");Thread.sleep(100);} catch (Exception e) {e.printStackTrace();}}
}

输出:

task-1 is running.
task-4 is running.
task-0 is running.
task-5 is running.
task-2 is running.
task-3 is running.

结果说明:可以发现一共打印出了6个任务的信息。

分析:corePoolSize设置为2,maxMumPoolSize设置为4,阻塞队列大小设置为2。所以,有2个任务会直接放入在线程池中运行,接下来会有2个任务放入阻塞队列中,又因为for循环创建了10个任务,所以当阻塞队列放满时,线程池还会创建2(maxMumPoolSize-corePoolSize)个线程来执行任务。后续会有4个任务被discard丢弃。所以一共执行了6个任务。

3、DiscardOldestPolicy 

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;public class DiscardOldestPolicyDemo {private static final int THREADS_SIZE = 2;private static final int MAX_MUM_POOLSIZE = 3;private static final int CAPACITY = 3;public static void main(String[] args) throws Exception {// 创建线程池。ThreadPoolExecutor pool = new ThreadPoolExecutor(THREADS_SIZE, MAX_MUM_POOLSIZE, 0, TimeUnit.SECONDS,new ArrayBlockingQueue<Runnable>(CAPACITY));// 设置线程池的拒绝策略为"DiscardOldestPolicy"pool.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardOldestPolicy());// 新建10个任务,并将它们添加到线程池中。for (int i = 0; i < 10; i++) {Runnable myrun = new MyRunnable("task-"+i);pool.execute(myrun);}// 关闭线程池pool.shutdown();}
}class MyRunnable implements Runnable {private String name;public MyRunnable(String name) {this.name = name;}public void run() {try {System.out.println(this.name + " is running.");Thread.sleep(200);} catch (Exception e) {e.printStackTrace();}}
}

输出结果:

task-0 is running.
task-1 is running.
task-5 is running.
task-7 is running.
task-8 is running.
task-9 is running.

结果说明:分析:corePoolSize设置为2,maxMumPoolSize设置为3,阻塞队列大小设置为3。前面2(0和1)个任务被线程直接执行,接下来三个(2、3、4)任务加入了队列中。此时阻塞队列满了。所以再创建1(maxMumPoolSize-corePoolSize)个线程执行任务5。再然后,继续提交的6,7,8,9会持续地往线程池中加入,此时因为队列已满,所以执行拒绝策略,删除队列中等待时间最久的任务。加入6,删除2,此时队列中是3,4,6。加入7,删除3,此时队列中是4,6,7。加入8,删除4,此时队列中是6,7,8。加入9,删除6,此时队列中剩下7,8和9。最终,当线程池中有空闲线程的时候,队列中的任务被执行,所以7,8和9任务被执行。

4、AbortPolicy 

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;public class AbortPolicyDemo {private static final int THREADS_SIZE = 2;private static final int MAX_MUM_POOLSIZE = 4;private static final int CAPACITY = 2;public static void main(String[] args) throws Exception {// 创建线程池。ThreadPoolExecutor pool = new ThreadPoolExecutor(THREADS_SIZE, MAX_MUM_POOLSIZE, 0, TimeUnit.SECONDS,new ArrayBlockingQueue<Runnable>(CAPACITY));// 设置线程池的拒绝策略为"抛出异常"pool.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());try {// 新建10个任务,并将它们添加到线程池中。for (int i = 0; i < 10; i++) {Runnable myrun = new MyRunnable("task-"+i);pool.execute(myrun);}} catch (RejectedExecutionException e) {e.printStackTrace();// 关闭线程池pool.shutdown();}}
}class MyRunnable implements Runnable {private String name;public MyRunnable(String name) {this.name = name;}public void run() {try {System.out.println(this.name + " is running.");Thread.sleep(200);} catch (Exception e) {e.printStackTrace();}}
}

输出结果:

task-0 is running.
task-1 is running.
task-4 is running.
task-5 is running.
java.util.concurrent.RejectedExecutionException: Task thread.MyRunnable@5e2de80c rejected from java.util.concurrent.ThreadPoolExecutor@1d44bcfa[Running, pool size = 4, active threads = 4, queued tasks = 2, completed tasks = 0]
    at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2063)
    at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:830)
    at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1379)
    at thread.AbortPolicyDemo.main(AbortPolicyDemo.java:27)
task-2 is running.
task-3 is running.

​​​​​​结果说明:分析:corePoolSize设置为2,maxMumPoolSize设置为4,阻塞队列大小设置为2。前面2(0和1)个任务被线程直接执行,接下来两个(2、3)任务加入了队列中。此时阻塞队列满了。所以再创建2(maxMumPoolSize-corePoolSize)个线程执行任务4和5。再然后,继续提交的6,7,8,9会持续地往线程池中加入,此时因为队列已满,所以执行abort拒绝策略,执行abort策略会抛出异常。最终,当线程池中有空闲线程的时候,阻塞队列中的任务被执行,所以2和3任务被执行。

5、CallerRunsPolicy 

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;public class CallerRunsPolicyDemo {private static final int THREADS_SIZE = 2;private static final int MAX_MUM_POOLSIZE = 4;private static final int CAPACITY = 2;public static void main(String[] args) throws Exception {// 创建线程池。ThreadPoolExecutor pool = new ThreadPoolExecutor(THREADS_SIZE, MAX_MUM_POOLSIZE, 0, TimeUnit.SECONDS,new ArrayBlockingQueue<Runnable>(CAPACITY));// 设置线程池的拒绝策略为"CallerRunsPolicy"pool.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());// 新建10个任务,并将它们添加到线程池中。for (int i = 0; i < 10; i++) {Runnable myrun = new MyRunnable("task-"+i);pool.execute(myrun);}// 关闭线程池pool.shutdown();}
}class MyRunnable implements Runnable {private String name;public MyRunnable(String name) {this.name = name;}public void run() {try {System.out.println(this.name + " is running.");Thread.sleep(100);} catch (Exception e) {e.printStackTrace();}}
}

输出结果:

task-1 is running.
task-6 is running.
task-4 is running.
task-0 is running.
task-5 is running.
task-7 is running.
task-2 is running.
task-3 is running.
task-8 is running.
task-9 is running.

结果说明:此策略是相对最可靠的策略,被提交的任务都会被执行,只是可能会出现一些延迟。

Java中线程池拒绝策略——代码讲解相关推荐

  1. 【Java 并发编程】线程池机制 ( 线程池阻塞队列 | 线程池拒绝策略 | 使用 ThreadPoolExecutor 自定义线程池参数 )

    文章目录 一.线程池阻塞队列 二.拒绝策略 三.使用 ThreadPoolExecutor 自定义线程池参数 一.线程池阻塞队列 线程池阻塞队列是线程池创建的第 555 个参数 : BlockingQ ...

  2. 线程池拒绝策略 开发中常用什么策略_面试官:说说你知道多少种线程池拒绝策略...

    往期文章 为什么阿里Java规约要求谨慎使用SimpleDateFormathttps://www.toutiao.com/i6696127929048367629/ 为什么我强烈推荐你用枚举来实现单 ...

  3. 面试官:说说你知道多少种线程池拒绝策略

    前言 线程池,相信很多人都有用过,没用过相信的也有学习过.但是,线程池的拒绝策略,相信知道的人会少许多. 四种线程池拒绝策略 当线程池的任务缓存队列已满并且线程池中的线程数目达到maximumPool ...

  4. 【多线程】线程池拒绝策略详解与自定义拒绝策略

    线程池的拒绝策略 ThreadPoolExecutor内部有实现4个拒绝策略,默认为AbortPolicy策略 CallerRunsPolicy:由调用execute方法提交任务的线程来执行这个任务 ...

  5. [Java高并发系列(5)][详细]Java中线程池(1)--基本概念介绍

    1 Java中线程池概述 1.1 什么是线程池? 在一个应用当中, 我们往往需要多次使用线程, 这意味着我们需要多次创建和销毁线程.那么为什么不提供一个机制或概念来管理这些线程呢? 该创建的时候创建, ...

  6. Java中线程池,你真的会用吗

    转载自   Java中线程池,你真的会用吗 在<深入源码分析Java线程池的实现原理>这篇文章中,我们介绍过了Java中线程池的常见用法以及基本原理. 在文中有这样一段描述: 可以通过Ex ...

  7. Java中线程池,你真的会用吗?

    在<深入源码分析Java线程池的实现原理>这篇文章中,我们介绍过了Java中线程池的常见用法以及基本原理. 在文中有这样一段描述: 可以通过Executors静态工厂构建线程池,但一般不建 ...

  8. java中线程池的使用_Java中线程池的简单使用

    什么是线程池? 顾名思义线程池就是线程的容器 举个例子:在没有共享电源的年代,车站有5个人手机都没电且都没有带电源,这五个人想要给手机充电只能去车站的售货亭各花100块钱买一个移动电源:但是现在共享电 ...

  9. 自定义线程池拒绝策略缓解高并发下线程池压力

    一. 默认的拒绝策略 ThreadPoolExceutor.AbortPolicy : 丢弃任务并抛出RejectedExecutionException异常.         ThreadPoolE ...

最新文章

  1. 记忆网络RNN、LSTM与GRU
  2. vscode使用markdown语言编写文本
  3. 非常好的JavaScript学习资源推荐
  4. bzoj1089 [SCOI2003]严格n元树(dp+高精)
  5. 译:Spring Data Repository 不区分大小写查询
  6. 一些非常有用的备忘录文档
  7. css定位:相对定位
  8. [密码学基础][每个信息安全博士生应该知道的52件事][Bristol Cryptography][第36篇]Index Calculus算法
  9. UI_布局_总体思路
  10. C++自己实现一个String类(腾讯阿里面试题目)
  11. codeforces 471B. MUH and Important Things 解题报告
  12. Linux用户空间与内核空间(理解高端内存)
  13. Eclipse调试时Application XXX is waiting for the debugger to attach的提示
  14. eWebEditor浏览器兼容 ie8 ie7
  15. ArcGIS模型构建器案例学习-批量删除空要素类地理模型
  16. tf.clip_by_global_norm详解
  17. 全连接神经网络、卷积神经网络
  18. ctf.show web2 最简单的SQL注入
  19. 打开 android studio 时遇到does not point to a valid
  20. lua游戏服务器热更新

热门文章

  1. 计算机组成原理分时传送电路设计,计算机组成原理和系统结构实验仪,FPGA设计,上海求育...
  2. Android - kotlin 协程极简入门
  3. vs code 插件收集
  4. KO88冲销工单结算
  5. 程序养身:初学者如何学瑜伽
  6. 年末系列(2)-加速器
  7. Effective C++条款39:明智而审慎地使用private继承(Use private inheritance judiciously)
  8. 用 Python 抓取公号文章保存成 PDF
  9. android界面布局
  10. c语言如何读出字符串中的数据,如何把数据存在字符串中