1. 线程池
- 降低资源消耗:通过池化技术重复利用已创建的线程,降低线程创建和销毁造成的损耗。
- 提高响应速度:任务到达时,无需等待线程创建即可立即执行。
- 提高线程的可管理性:线程是稀缺资源,如果无限制创建,不仅会消耗系统资源,还会因为线程的不合理分布导致资源调度失衡,降低系统的稳定性。使用线程池可以进行统一的分配、调优和监控。
2. Java中线程池
Java开发,我们使用JDK环境,开发框架基本都是Spring全家桶。线程池的基础原理都在JDK中,JDK1.5新增线程池相关类,在核心jar包中,下面。
2.1 JDK中线程池
java线程池基础知识
线程UML.png
可以看出,包含三个线程池:,,。
- 是Java 1.7 引入的一种新的并发框架,核心思想是将大的任务拆分成多个小任务(fork),然后在将多个小任务处理汇总到一个结果上(join),充分利用多cpu,多核CPU的优势,引入了“work-stealing”机制,更有效的利用线程。
- 是 java常用的线程池,提供基础的线程池功能。初始化传入不同类型的工作队列和拒绝策略参数,可以定制不同类型和功能的线程池,应用最为广泛。
- 从类图上可以看出,它继承了ThreadPoolExecutor,并实现了ScheduledExecutorService,是对ThreadPoolExecutor做的功能扩展,本质上是一个使用线程池执行定时任务的类,可以用来在给定延时后执行异步任务或者周期性执行任务,较任务调度的Timer来说,其功能更加强大。
2.2 JDK中提供的几类线程池
JDK中,使用给创建了几个不同功能种类的线程池,可以调出来看看:
看一下都有什么特点:
线程池名称 使用阻塞队列 特点 newFixedThreadPool LinkedBlockingQueue() 1、核心线程数和最大线程数相同
2、由于keepAliveTime设置为0,当线程创建后会一直存在
3、由于用的是无界队列所以可能会导致OOM newSingleThreadExecutor LinkedBlockingQueue() 1、核心线程数和最大线程数都为1单线程
2、无界队列可能导致OOM newCachedThreadPool SynchronousQueue() 1、核心线程数为0,最大线程数为Integer.MAX_VALUE
2、当没任务时线程存活时间为60秒
3、使用的是0大小的队列,所以不存储任务,只做任务转发 newScheduledThreadPool DelayedWorkQueue() 1、执行周期任务
2、无界队列,可能会导致OOM
2、由于keepAliveTime设置为0,当线程创建后会一直存在
3、由于用的是无界队列所以可能会导致OOM newSingleThreadExecutor LinkedBlockingQueue() 1、核心线程数和最大线程数都为1单线程
2、无界队列可能导致OOM newCachedThreadPool SynchronousQueue() 1、核心线程数为0,最大线程数为Integer.MAX_VALUE
2、当没任务时线程存活时间为60秒
3、使用的是0大小的队列,所以不存储任务,只做任务转发 newScheduledThreadPool DelayedWorkQueue() 1、执行周期任务
2、无界队列,可能会导致OOM
3. Spring中的线程池
Spring中的线程池和JDK中的基本一样,在包下面。
和JDK中对应的,Spring的顶层接口是,它实现了JDK中的接口。
Spring中常用的线程池是,它是是借助于JDK并发包中的来实现的。
要想使用线程池,先了解一下线程池中的一些参数:
3.1 线程池用到的一些参数
参数
也就这几个常用参数,在下面使用中再介绍意思。
3.2 使用自定义线程池
- 3.2.1 线程池配置类
上面配置了线程池,并生成了线程池bean,交给了Spring容器管理,使用时注入即可使用。
- 3.2.2 使用线程池
SpringBoot使用线程池注意2点:- 添加注解开启异步,即多线程
- 在要使用的方法上加上注解,括号内是线程池名字
- 3.2.3 @Async失效情况:
-
- 异步方法使用static修饰
- 2.异步类没有使用@Component注解(或其他注解)导致spring无法扫描到异步类
-
- 异步方法不能与被调用的异步方法在同一个类中
-
- 类中需要使用@Autowired或@Resource等注解自动注入,不能自己手动new对象
-
- 如果使用SpringBoot框架必须在启动类中增加@EnableAsync注解
3.3 SpringBoot中自动装配的线程池
SpringBoot线程池自动装配在这个jar中,在类中。
自动装配条件:
条件
自动装配的Bean名字给了2个,一个是,一个是。如果自动装配了,可以直接注入使用。
Bean
4. 线程池处理任务流程:
- 如果池中任务数 < corePoolSize (核心线程数),创建新线程立即执行任务
- 如果池中任务数 > corePoolSize,新任务放到缓存队列当中等待执行
- 队列满,线程数量<maxPoolSize,新建线程立即执行任务
- 队列满,线程数量>=maxPoolSize,使用拒绝策略拒绝
所以使用线程池,需要注意:
- 搞懂执行流程,设置合适的 、和队列容量,避免延时任务,一般队列容量不会像默认值那么大,否则可能等很长时间;
- 注意使用时一些注解加上
- 要了解线程的一些基础知识,比如生命周期等。
Java多线程--线程的状态 - 简书 (jianshu.com)
版权声明:
本文来源网络,所有图片文章版权属于原作者,如有侵权,联系删除。
本文网址:https://www.bianchenghao6.com/h6javajc/24604.html