【Java 并发编程】线程池机制 ( 线程池阻塞队列 | 线程池拒绝策略 | 使用 ThreadPoolExecutor 自定义线程池参数 )
文章目录
- 一、线程池阻塞队列
- 二、拒绝策略
- 三、使用 ThreadPoolExecutor 自定义线程池参数
一、线程池阻塞队列
线程池阻塞队列是线程池创建的第 555 个参数 : BlockingQueue<Runnable> workQueue
;
public ThreadPoolExecutor(int corePoolSize, // 核心线程数 , 这些线程基本不会被销毁int maximumPoolSize, // 最大线程数 , 线程池能创建的最大线程数量long keepAliveTime, // 空闲情况下 , 非核心线程存活时间TimeUnit unit, // 空闲时间单位BlockingQueue<Runnable> workQueue,// 任务的阻塞队列 ★ThreadFactory threadFactory, // 创建线程的工厂类RejectedExecutionHandler handler) // 拒绝策略
线程池阻塞队列 : 线程池中的阻塞队列 , 同一时刻 , 只能有 111 个线程访问队列 , 执行任务 入队 / 出队 操作 ; 队列都是 FIFO 先进先出 ;
阻塞队列相关概念 :
- 大小边界 :
- 有界 : 阻塞队列 大小有限制 , 不是无限大的 ;
- 无界 : 阻塞队列 理论上无限大 , 比如设置成
Integer.MAX_VALUE
;
- 队列已满 : 只能出队 , 不能入队 ; 入队操作需阻塞等待 ;
- 队列为空 : 只能入队 , 不能出队 ; 出队操作需要等待 ;
- 大小边界 :
ArrayBlockingQueue
: 有界阻塞队列 , 需要 指定阻塞队列大小 ;LinkedBlockingQueue
: 无界阻塞队列 , 基于链表的阻塞队列 ;Executors.newCachedThreadPool()
或Executors.newFixedThreadPool(10)
方法创建的线程池 , 使用的是该阻塞队列 ;
SynchronousQueue
: 队列 不存储元素 , 后一个Runnable
任务入队 , 必须等到前一个任务执行完毕才可以 , 否则会一直阻塞等待 ;Executors.newCachedThreadPool()
方法创建的线程池 , 使用的是该阻塞队列 ;
PriorityBlockingQueue
: 有优先级的阻塞队列 ;
阻塞队列吞吐量 : SynchronousQueue
> LinkedBlockingQueue
> ArrayBlockingQueue
;
二、拒绝策略
线程池拒绝策略是线程池创建的第 777 个参数 : RejectedExecutionHandler handler
;
public ThreadPoolExecutor(int corePoolSize, // 核心线程数 , 这些线程基本不会被销毁int maximumPoolSize, // 最大线程数 , 线程池能创建的最大线程数量long keepAliveTime, // 空闲情况下 , 非核心线程存活时间TimeUnit unit, // 空闲时间单位BlockingQueue<Runnable> workQueue,// 任务的阻塞队列 ThreadFactory threadFactory, // 创建线程的工厂类RejectedExecutionHandler handler) // 拒绝策略 ★
线程池拒绝策略 : 如果核心线程 , 非核心线程都在执行任务 , 阻塞队列是有界的 , 也满了 , 此时线程池如果再添加任务 , 就会触发如下拒绝策略 ;
- DiscardPolicy : 丢弃任务 ;
- DiscardOldestPolicy : 丢弃队头的最旧的任务 ;
- AbortPolicy : 抛出异常 , 这也是默认方式 ;
- CallerRunsPolicy : 调用者自行处理 ;
线程池默认的拒绝策略是 抛出异常 方式 ;
private static final RejectedExecutionHandler defaultHandler =new AbortPolicy();
三、使用 ThreadPoolExecutor 自定义线程池参数
创建 111 个线程池 , 核心线程数是 222 , 最大线程数是 333 , 则非核心线程 0 ~ 1 个 , 非核心线程最大空闲存活时间 60 秒 , 阻塞队列最大存放 10 个元素 , 拒绝策略设置为抛出异常方式 , 如果阻塞队列装满 , 再次尝试执行新任务时 , 会抛出异常 ;
代码示例 :
import java.util.concurrent.*;public class Main {public static void main(String[] args) {ExecutorService executorService = new ThreadPoolExecutor(2, // 核心线程数 23, // 最大线程数 3, 非核心线程 0 ~ 1 个60, // 非核心线程最大空闲存活时间 60 秒TimeUnit.SECONDS,new ArrayBlockingQueue<>(10), // 阻塞队列, 最大存放 10 个元素Executors.defaultThreadFactory(), // 线程工厂new ThreadPoolExecutor.AbortPolicy() // 决绝策略, 如果执行任务失败, 抛出异常);for (int i = 0; i < 20; i ++) {executorService.execute(new Task(i));}}static class Task implements Runnable {/*** 记录线程的索引 0 ~ 99*/private int i = 0;public Task(int i) {this.i = i;}@Overridepublic void run() {System.out.println("线程 ID : " + Thread.currentThread().getName() + " , 线程索引 : " + i);try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}
}
执行结果 : 这里线程最大执行到了 121212 , 也就是从 000 开始计数 , 执行了 131313 个任务 , 其中 333 个线程池各自执行一个任务 , 阻塞队列存放 101010 个任务 , 再次尝试将第 141414 个任务放入阻塞队列时 , 报出 java.util.concurrent.RejectedExecutionException
异常 , 但是队列中的 101010 个任务也正常执行完毕 ;
线程 ID : pool-1-thread-2 , 线程索引 : 1
线程 ID : pool-1-thread-3 , 线程索引 : 12
线程 ID : pool-1-thread-1 , 线程索引 : 0
Exception in thread "main" java.util.concurrent.RejectedExecutionException:
Task Main$Task@5cad8086 rejected from java.util.concurrent.ThreadPoolExecutor@6e0be858
[Running, pool size = 3, active threads = 3, queued tasks = 10, completed tasks = 0]at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2047)at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:823)at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1369)at Main.main(Main.java:16)
线程 ID : pool-1-thread-3 , 线程索引 : 2
线程 ID : pool-1-thread-1 , 线程索引 : 4
线程 ID : pool-1-thread-2 , 线程索引 : 3
线程 ID : pool-1-thread-1 , 线程索引 : 5
线程 ID : pool-1-thread-2 , 线程索引 : 7
线程 ID : pool-1-thread-3 , 线程索引 : 6
线程 ID : pool-1-thread-1 , 线程索引 : 9
线程 ID : pool-1-thread-2 , 线程索引 : 8
线程 ID : pool-1-thread-3 , 线程索引 : 10
线程 ID : pool-1-thread-2 , 线程索引 : 11
【Java 并发编程】线程池机制 ( 线程池阻塞队列 | 线程池拒绝策略 | 使用 ThreadPoolExecutor 自定义线程池参数 )相关推荐
- Java并发编程之锁机制之LockSupport工具
关于文章涉及到的jdk源码,这里把最新的jdk源码分享给大家----->jdk源码 前言 在上篇文章<Java并发编程之锁机制之AQS(AbstractQueuedSynchronizer ...
- Java并发编程与技术内幕:线程池深入理解
林炳文Evankaka原创作品.转载请注明出处http://blog.csdn.net/evankaka 摘要: 本文主要讲了Java当中的线程池的使用方法.注意事项及其实现源码实现原理,并辅以实例加 ...
- Java 并发编程解析 | 如何正确理解Java领域中的锁机制,我们一般需要掌握哪些理论知识?
苍穹之边,浩瀚之挚,眰恦之美: 悟心悟性,善始善终,惟善惟道! -- 朝槿<朝槿兮年说> 写在开头 提起Java领域中的锁,是否有种"道不尽红尘奢恋,诉不完人间恩怨"的 ...
- 【面试】Java 并发编程
并发编程 1. 进程与线程的区别 线程上下文切换比进程上下文切换快的原因 谈谈你对守护线程的理解 守护线程和用户线程有什么区别? 线程的 run() 和 start() 有什么区别? 2. 多线程与单 ...
- 8w字 | Java并发编程 全套功法
介绍:CSDN统计字数:77153字,Java多线程从入门到精通,由浅入深.[建议收藏!] ❤️❤️❤️❤️❤️❤️ 点击主页发现更多好文❤️❤️❤️❤️❤️❤️ 文章目录 引言 什么是进程,线程? ...
- Java并发编程:阻塞队列
2019独角兽企业重金招聘Python工程师标准>>> 本文先讲述一下java.util.concurrent包下提供主要的几种阻塞队列,然后分析了阻塞队列和非阻塞队列的中的各个方法 ...
- 【Java 并发编程】线程池机制 ( ThreadPoolExecutor 线程池构造参数分析 | 核心线程数 | 最大线程数 | 非核心线程存活时间 | 任务阻塞队列 )
文章目录 前言 一.ThreadPoolExecutor 构造参数 二.newCachedThreadPool 参数分析 三.newFixedThreadPool 参数分析 四.newSingleTh ...
- 【Java 并发编程】线程池机制 ( 线程池示例 | newCachedThreadPool | newFixedThreadPool | newSingleThreadExecutor )
文章目录 前言 一.线程池示例 二.newCachedThreadPool 线程池示例 三.newFixedThreadPool 线程池示例 三.newSingleThreadExecutor 线程池 ...
- 【Java 并发编程】线程池机制 ( 线程池执行任务细节分析 | 线程池执行 execute 源码分析 | 先创建核心线程 | 再放入阻塞队列 | 最后创建非核心线程 )
文章目录 一.线程池执行任务细节分析 二.线程池执行 execute 源码分析 一.线程池执行任务细节分析 线程池执行细节分析 : 核心线程数 101010 , 最大小成熟 202020 , 非核心线 ...
最新文章
- 特斯拉遇上 CPU:程序员的心思你别猜
- MATLAB读取文本文件----textread
- python自带库处理excel-python处理excel之第三方库openpyxl
- TCP/IP协议(二)tcp/ip基础知识
- Android系统如何实现UI的自适应
- Jenkins连接TFS出现错误:“jenkins com.microsoft.tfs.core.exceptions.TECoreException”的问题收集...
- 微信小程序轮播图中间变大_微信小程序实现带放大效果的轮播图
- 【Java】输入三角形的三边长,求三角形的面积
- Nvelocity 第二章 注释语法
- VS2015正确卸载方法,亲测
- Winform微信扫码支付
- log10/log2--求常用对数/以2为底的对数
- [python爬虫之路day4]:xpath基本知识lxml结合xpath进行数据分析爬取豆瓣电影
- Pascal voc 数据集xml格式解析
- Arduino ESP8266利用定时器中断控制LED闪烁示例程序
- php 插件推荐,Typecho实用插件推荐(一)
- Mac自带FTP工具用法
- NSGA-3优化算法介绍及案例实现(三个测试函数DTLZ1、DTLZ2和DTLZ3)
- hyu 1698 Just a Hook
- 2018年我国互联网网络安全态势综述