ThreadPoolExecutor BlockingQueue讲解
有四种常用阻塞队列策略:
1.直接拒绝:(Direct Handoffs)
一个好的工作队列应该是不缓存任务,而是直接交给线程处理,就如SynchronousQueue一样。一个任务将会入队失败,如果没有线程执行它,也就是说每次都会创建一个新线程。这样做有什么好处呢?
当有一批内部有相互依赖的任务需要要执行时,不会因为需要长时间等待其它任务而被锁住。一般都会将maximumPoolSizes设置为没有限制,避免新创建的任务被拒绝。但有一个缺点是:当新任务提交的速度比被线程消费的速度快时,会造成无限制的线程增长,导致系统load过高,甚至OOM。
2.无界队列(Unbounded Queue):
如果使用没有界限的队列(如LinkedBlockingQueue),则当新任务到来时,发现线程池中的线程数达到corePoolSize大小时,很不幸,他就会被加入队列,等待线程池中有线程执行完任务来读取。也就意味着,线程池中的线程数不会超过corePoolSize。当任务之间相互独立时,适合使用无界队列,例如,一个web服务器,使用无界队列可以缓和瞬间激增的请求对服务器的压力。但是当任务提交的速度比处理速度快时,会导致无界对列不断增涨。
3. 有界队列(Bounded Queue)
如果使用有界队列,例如: ArrayBlockingQueue, 则当新任务到来时,发现线程池中的线程数达到corePoolSize大小时,也会被加入队列,但当队列满时,会创建新的线程去执行任务,直到达到maxPoolSize。如果达到maxPoolSize,仍有任务到来,则会调用拒绝策略进行拒绝操作。当任务没有很高的及时性要求,也不想占用服务器过多CPU资源时, 可以考虑缓存一部分任务,并设置线程数的最高值。
4. 优先级队列(Priority Queue)
顾名思意,优先级队列,适合于具有优先级的任务。优先级队列也是一种有界队列,但与有界队列不同的时,有界队列在一开始就界定了大小,而优先级队列可以设置一个初始大小,当空间不够时,会自动扩容,直到(Integer.MAX_VALUE - 8)。例如: 转账任务,优先给VIP客户转账;
为什么最大是Integer.MAX_VALUE - 8?
我们看下JDK中的描述:
Some VMs reserve some header words in an array.
Attempts to allocate larger arrays may result in
OutOfMemoryError: Requested array size exceeds VM limit
意思是有一些JVM虚拟机会在数组中保留Header, 如果分配更大的长度,会超成OOM。这段注释只说明了为什么要减去8,因为Header信息占8个字节,那为什么是Integer.MAX_VALUE,因为数组的长度类型是非负的int类型, 这也是JVM规范规定的。比如String类型,它的底层是使用字符数组存储,所以String占用的最大内存空间是(Integer.MAX_VALUE - 8)*一个字符占的空间。看一些文章说一个字符占2个字节,其实是不准确的,因为不同的编码格式,字符对应的编码结果是不一样的,占用的内存空间当然也不一样的。比如我们常用的UTF-8编码,一个汉字可能占用2,3,4个字节,长度并不是固定的。
ThreadPoolExecutor BlockingQueue讲解的更多相关文章
- JAVA并发(8)-ThreadPoolExecutor的讲解
很久前(2020-10-23),就有想法学习线程池并输出博客,但是写着写着感觉看不懂了,就不了了之了.现在重拾起,重新写一下(学习一下). 线程池的优点也是老生常谈的东西了 减少线程创建的开销(任务数 ...
- ThreadPoolExecutor参数讲解
1. 线程池可以节省创建多个线程带来的开销问题. 2. 线程池的参数如下: public ThreadPoolExecutor(int corePoolSize, int maximumPoolSiz ...
- 原创:ThreadPoolExecutor线程池深入解读(一)----原理+应用
本文档,适合于对多线程有一定基础的开发人员.对多线程的一些基础性的解读,请参考<java并发编程>的前5章. 对于源代码的解读,本人认为可读可不读.如果你想成为一位顶级的程序员,那就培养自 ...
- 简单实现java线程池
使用多线程以及线程池的意义无需多说,要想掌握线程池,最好的方法还是自己手动去实现. 一.实现思路 (网络盗图) 二.实现代码 1.线程池类 package com.ty.thread; im ...
- netty系列之:NIO和netty详解
目录 简介 NIO常用用法 NIO和EventLoopGroup NioEventLoopGroup SelectorProvider SelectStrategyFactory RejectedEx ...
- 线程池系列二:ThreadPoolExecutor讲解
一.简介 1)线程池类为 java.util.concurrent.ThreadPoolExecutor,常用构造方法为: ThreadPoolExecutor(int corePoolSize, i ...
- Executors、ThreadPoolExecutor线程池讲解
官方+白话讲解Executors.ThreadPoolExecutor线程池使用 Executors:JDK给提供的线程工具类,静态方法构建线程池服务ExecutorService,也就是Thread ...
- 线程池原理讲解——ThreadPoolExecutor
[这是前几天的存货,留着没发表,今天又复习一遍,润化了部分内容,继续干] 说线程池前,先简单回顾一下线程的状态吧: 1.线程状态转换 线程的五种状态,及其转换关系: 2.线程创建方式 三种:两个接口一 ...
- ThreadPoolExecutor使用和思考(上)-线程池大小设置与BlockingQueue的三种实现区别
工作中多处接触到了ThreadPoolExecutor.趁着现在还算空,学习总结一下. 前记: jdk官方文档(javadoc)是学习的最好,最权威的参考. 文章分上中下.上篇中主要介绍ThreadP ...
随机推荐
- Go语言Tips
时间日期格式化 time.Now().Format("2006-01-02") 原生DefaultServeMux支持restful路由 ref: https://towardsd ...
- HCIA-Datacom 2.1 实验一:IPv4编址及IPv4路由基础实验
实验目的 掌握接口IPv4地址的配置方法 理解LoopBack接口的作用与含义 理解直连路由的产生原则 掌握静态路由的配置方法并理解其生效的条件 掌握通过PING工具测试网络层联通性 掌握 ...
- pnpm凭什么这么快
前端包管理器层出不穷,pnpm算是一个后起之秀.它和npm有什么不同,为什么有了npm还要造一个pnpm? npm的问题 npm是最早的包管理器,安装nodejs自带npm,v3版本之前,npm安全依 ...
- iOS越狱进度,越狱工具,一篇文章搞定
最新的 iOS 越狱状态 iOS 15.0 – 16.0 Beta 目前无法越狱, Cheyote Jailbreak 正在开发中. iOS 14.6 -> 14.8 目前在某些较新的设备(A1 ...
- Cannot resolve method 'println(java.lang.String)'
jsp文件中println爆红 <% int sum = 0; for (int i = 1; i <=100 ; i++) { sum+=i; } out.println("& ...
- 【JAVA】学习路径64-补充-编写一个会抛异常的方法
有一些方法,在调用的时候有可能会出错,所以我们使用这些方法的时候会使用try catch. 比如InputStream里面的read()方法等等,那么这些方法是怎么实现抛异常的效果的呢? 能抛异常的方 ...
- B2. Wonderful Coloring - 2
链接:Problem - 1551B2 - Codeforces 题意:有m个颜色,要求每种颜色内的数字各不相同,问,颜色的最大长度多少. 题解: 判断每个数字的个数,如果大于m,那么最大长度就加一 ...
- 细数实现全景图VR的几种方式(panorama/cubemap/eac)
Three.js系列: 在元宇宙看电影,享受 VR 视觉盛宴 Three.js系列: 造个海洋球池来学习物理引擎 Three.js系列: 游戏中的第一.三人称视角 Three.js系列: 数实现全景图 ...
- 记一次 Sedona(GeoSpark) 空间计算优化
项目需求需要空间计算能力,开始选型Sedona(GeoSpark)来完成, 需求需要每一条数据在满足某条件的情况下,去查找某张表进行空间匹配,找到离这个点(point)最近的一条道路(lineStri ...
- 【读书笔记】C#高级编程 第二十二章 安全性
(一)身份验证和授权 安全性的两个基本支柱是身份验证和授权.身份验证是标识用户的过程,授权在验证了所标识用户是否可以访问特性资源之后进行的. 1.标识和Principal 使用标识可以验证运行应用程序 ...