搞懂Java线程池
作者:yes的练级手册 发布时间:2021-08-04 10:01:06
身为程序员我们对线程是再熟悉不过了,多线程并发算是Java进阶的知识,用好多线程不容易有太多的坑。创建线程也算是一个"重"操作。创建线程的语句是new Thread()咋一看好像就是new了一个对象。
没错是new了个对象,但是不仅仅是普通对象那样在堆中分配了一块内存,它还需要调用操作系统内核API,然后操作系统再为线程分配一些资源。所以较普通对象,线程就比较“重了”。所以我们要避免频繁的创建和销毁线程,还得控制一下线程的数量。线程池就是用来完成这一项使命的。
所以多线程就离不开线程池,所以要掌握多线程编程,线程池的了解必不可少。
线程池的设计就是采用生产者-消费者模式,线程池里面的线程是消费者,我们塞给线程池的任务是生产者。可以理解成线程池就是火车站售票厅,线程池里面的线程就是火车站售票厅窗口员工,我们去买票或者退票改签就是给窗口员工任务也就是生产,然后窗口员工帮我们办理业务,也就是消费。
一般我们是用ThreadPoolExecutor来创建线程池,我找了里面参数最多的构造器。
1、corePoolSize
按字面翻译过来就是核心池大小,其实就是线程池保有的最小的线程数,这里需要注意一下,初始化线程池的时候,除非调用prestartAllCoreThreads或者prestartCoreThread这两个方法,这两个方法分别是在无任务到来之前预创建所有核心线程或者创建一个线程。否则线程池初始化后没任务进来前是没有线程的。只有当任务来了才会创建线程。
所以这里保有的核心数指的是,当线程池创建了这么多的线程之后,会保留的不会被回收的线程数,超过corePoolSize的线程在一定时间之后就会被回收。
但是java1.6新增了一个allowCoreThreadTimeOut(boolean value)方法,当设为true时候,所有的线程都会超时回收,包括核心线程。
2、maximumPoolSize
最大线程数,也就是池里面能有的最大的线程数量。也就是火车站售票厅窗口所有的窗口都有员工在服务。特别是在节假日的时候,基本上窗口都会开放。
3、keepAliveTime、TimeUnit
keepAliveTime就是存活时间,TimeUnit是时间单位,来表明keepAliveTime的数字是秒啊还是毫秒啊等等。
这两个参数就是当我们线程池存在的线程数量超过corePoolSize时,如果有个线程已经空闲了keepAliveTime这么长的时间,那么这个空闲线程就要被回收了,就类似于出行高峰期过去了,售票厅窗口可以关闭几个了。总不能都没人了还开这么多窗口把,浪费呀。
4、workQueue
工作队列,是阻塞队列。队列存储的也就是线程需要执行的Runnable,也就是任务。对应着就是去售票厅排队的我们。
5、threadFactory
按名字翻译过来就是线程工厂了,也就是我们可以搞个工厂,然后自定义如何创建线程,比如给线程set下名字啊等。然后线程池就会按照工厂定义的方式创建线程。就是如果不设定线程的名字的话,线程名可能就是什么thread-1这样的,对于我们排查问题不太方便,所以给个名字来标识一下比较好。
6、handler
这个是拒绝策略,也就是当线程池中所有的线程都在执行任务,并且工作队列(是有界队列)也排满了,那再有任务提交就会执行拒绝策略。ThreadPoolExecutor提供了四种拒绝策略
1、ThreadPoolExecutor.AbortPolicy()
是默认的拒绝策略,会抛出 RejectedExcecutionException。
2、ThreadPoolExecutor.CallerRunsPolicy()
让提交任务的线程自己去执行这个任务。。好像这样做挺有道理的..我没空你自己搞去
3、ThreadPoolExecutor.DiscardOldestPolicy()
丢弃最老的任务,也就是工作队列里最前面的任务,丢弃了之后把新任务加入到工作队列中...真的不公平啊
4、ThreadPoolExecutor.DiscardPolicy()
直接丢弃任务,并且不抛出任何异常...假装没看到系列
除了这四种还可以自定义拒绝策略,建议自定义拒绝策略。因为更加的友好,可以设置成服务降级啊等操作。
注意
Java并发包还提供了Executors,可以快速创建线程池,但是不推荐使用Executors。因为Executors创建线程池都是默认使用 * 队列LinkedBlockingQueue,在高负载的情况下容易OOM。所以建议使用有界队列。
总结
所以线程池就是生产者-消费者模型的实现,线程池约束了线程的数量,也避免频繁的创建和销毁线程。工作队列得存在使得任务有序的进行,完美!
以上所述是小编给大家介绍的Java线程池详解整合网站的支持!
来源:https://juejin.im/post/5cbaf0dd6fb9a068744e7beb


猜你喜欢
- 目录前言准备工作Nacos安装及使用入门准备三个SpringBoot服务,引入Nacos及Kafka业务解读Nacos配置创建配置读取配置监
- 先要把word或ppt转换为pdf; 以pdf的格式展示,防止文件拷贝。转换方法1、安装Word、Excel、PowerPoint组件注意:
- 序言小编在项目中有遇到使用 flutter 实现扫码枪接入的需求。为方便使用,小编把能力封装成 package 并发布。好记性不如烂笔头,下
- 前言在工作中,比如要实现一个功能,前端传什么参数,后端的controller层中怎么接收参数 ,封装成了什么实体对象,有些参数是在URL上使
- 本文实例讲述了java Swing组件setBounds()简单用法。分享给大家供大家参考,具体如下:先看API:public void s
- rocketmq消费者注册监听有两种模式有序消费MessageListenerOrderly和并发消费MessageListenerConc
- 面向对象的程序是由对象组成的,每个对象包含对用户公开的特定功能部分和隐藏的实现部分。在面向对象程序设计(OOP)中,不必关心对象的具体实现。
- Java实现按行读取大文件String file = "F:" + File.separator + "a.t
- 1.下载jenkins 下载地址:https://jenkins.io/  
- java中如何表示圆周率设计一个Shape接口和它的两个实现类Square和Circle。 要求如下(1) Shape接口中有一个抽象方法a
- 通常用java来打包文件生成压缩文件后,有如下两个地方会出现乱码 :1、内容的中文乱码问题,这个问题网上很多人给出了解决方法,主要有两种方法
- 缘起公司医疗业务人手比较少【小而美】的团队~ 较少采用的前端技术架构是:toC:小程序 toB2C: Flutter + H5(SPA -
- 本文实例讲述了Java针对ArrayList自定义排序的2种实现方法。分享给大家供大家参考,具体如下:Java中实现对list的自定义排序主
- 一、访问控制url匹配在前面讲解了认证中所有常用配置,主要是对http.formLogin()进行操作。而在配置类中 http.author
- 近日工程中,逐渐感觉到原来复制粘贴代码的笨重,突然想起以前有人和我说起过Git和SVN之类的版本管理工具。由于平时主要是写Java代码,所以
- 在游戏开发中,主角需要通过跑地图来通关升级,本章主要介绍主角的移动和摄像跟随的操作。主角移动角色位移通过主角的骨骼动画控制(后续文章会详细介
- Android listview的滑动冲突解决方法在Android开发的过程中,有时候会遇到子控件和父控件都要滑动的情况,尤其是当子控件为l
- MyBatis 是一款常用的持久层框架,使得程序能够以调用方法的方式执行某个指定的SQL,将执行SQL的底层逻辑进行封装。多数与Spring
- 本文将介绍Java在ICPC快速IO实现方法,下面看看
- 基础环境SpringBoot、Maven代码实现1.添加依赖<!--二维码生成 --><dependency&