当前位置: 首页 > 编程笔记 >

搞懂Java线程池

澹台昆
2023-03-14
本文向大家介绍搞懂Java线程池,包括了搞懂Java线程池的使用技巧和注意事项,需要的朋友参考一下

身为程序员我们对线程是再熟悉不过了,多线程并发算是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线程池详解整合,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对小牛知识库网站的支持!

 类似资料:
  • 本文向大家介绍一文搞懂JAVA 枚举(enum),包括了一文搞懂JAVA 枚举(enum)的使用技巧和注意事项,需要的朋友参考一下 Java 枚举是一个特殊的类,一般表示一组常量,比如一年的 4 个季节,一个年的 12 个月份,一个星期的 7 天,方向有东南西北等。 Java 枚举类使用 enum 关键字来定义,各个常量使用逗号 , 来分割。 例如定义一个颜色的枚举类。 以上枚举类 Color 颜

  • 本文向大家介绍彻底搞懂Python字符编码,包括了彻底搞懂Python字符编码的使用技巧和注意事项,需要的朋友参考一下 不论你是有着多年经验的 Python 老司机还是刚入门 Python 不久,你一定遇到过UnicodeEncodeError、UnicodeDecodeError 错误,每当遇到错误我们就拿着 encode、decode 函数翻来覆去的转换,有时试着试着问题就解决了,有时候怎么试

  • 大家好,今天给大家介绍一个非常热门的技术,同时也是面试的时候面试官特别喜欢问的一个话题,那就是 SpringCloudAlibaba 的底层原理。 现在大家都知道,SpringCloudAlibaba 风靡 Java 开发行业,各个公司都在用这套技术,所以咱们 Java 工程师出去面试,面试官对 SpringCloudAlibaba 都搞成了面试必问选项了,但凡面试,总会有面试官问问:“兄弟,Sp

  • 本文向大家介绍快速搞懂Android口令加密(一),包括了快速搞懂Android口令加密(一)的使用技巧和注意事项,需要的朋友参考一下 废话不多说了,直接给大家贴代码了。 使用加密方法: 以上内容是针对Android口令加密的相关介绍,希望对大家有所帮助!

  • 本文向大家介绍彻底搞懂PHP 变量结构体,包括了彻底搞懂PHP 变量结构体的使用技巧和注意事项,需要的朋友参考一下 PHP5 中的 zval 多数文章,在提到PHP5 变量结构体的时候,都提到:sizeof(zval) == 24, sizeof(zvalue_value) == 16,实际上这个论述并不准确,在 CPU 为 64bit 时,这个结果是正确的。 但当 CPU 为32bit 时: s

  • 一面问了很多项目的深挖 二面上来没有自我介绍,直接手写 K_means聚类算法,憋着写了一半,没写完。 然后就结束面试了,问了我啥时候能到岗,一周能实习几天,然后就没了 有点搞不懂这个面试😢#第一次面试##Momenta##我的实习求职记录#