异步使用场景+线程池
01 异步场景
异步使用的场景:
文件导出时,要获取一系列操作:
(1)先将前端传的文件上传到公司tos平台,将数据存入数据库。
(2)定时任务扫数据库/也可以通过消息队列完成,调用机器人发送通知给用户:需要两次http请求:机器人要获取发送消息的token,然后机器人再调用http请求给用户发送消息。
(1)和(2)串行操作的话,用户收到“已经导出完成,请到lark查看”等待时间会很长,并行的话,(1)执行完成后,用户就收到“已经导出完成,请到lark查看”,用户切换到lark的过程中,大概1s的时间,(2)就执行完成,用户就能看到导出的文件了。
可能存在的问题:用户看到了提示“已经导出完成,请到lark查看”,但是切换到lark时会有两种情况:
(1) 没有及时看到文件,过了一会才看到,这可能是超时重试的结果
(2)用户没有看到问题,因为重试几次后都失败了,所以会在报警群里报警,这个时候就只能用户再重新导出了。
2. 线程池也是异步操作:
调用DWS时,先像池子里面提交任务,提交之后就里面返回,等到dept_task.result()时会一直轮训查询的结果。
02 为什么要用线程池
我们看看不使用线程池有哪些坏处。
频繁的线程创建和销毁会占用更多的CPU和内存
频繁的线程创建和销毁会对GC产生比较大的压力
线程太多,线程切换带来的开销将不可忽视
线程太少,多核CPU得不到充分利用,是一种浪费
使用线程池可以带来一系列好处:
降低资源消耗:通过池化技术重复利用已创建的线程,降低线程创建和销毁造成的损耗。
提高响应速度:任务到达时,无需等待线程创建即可立即执行。
提高线程的可管理性:线程是稀缺资源,如果无限制创建,不仅会消耗系统资源,还会因为线程的不合理分布导致资源调度失衡,降低系统的稳定性。使用线程池可以进行统一的分配、调优和监控。
提供更多更强大的功能:线程池具备可拓展性,允许开发人员向其中增加更多的功能。比如延时定时线程池ScheduledThreadPoolExecutor,就允许任务延期执行或定期执行。
03 线程池原理
corePool -> 核心线程池
maximumPool -> 线程池最大线程数
BlockQueue -> 队列
RejectedExecutionHandler -> 拒绝策略
corePoolSize就是线程池中的核心线程数量,这几个核心线程,在没有用的时候,也不会被回收。
maximumPoolSize就是线程池中可以容纳的最大线程的数量,
而keepAliveTime,就是线程池中除了核心线程之外的其他的最长可以保留的时间,也就是非核心线程可以保留的最长的空闲时间,而util,就是计算这个时间的一个单位,
workQueue,就是等待队列,任务可以储存在任务队列中等待被执行,执行的是FIFIO原则(先进先出)。
threadFactory,就是创建线程的线程工厂,最后一个handler,是一种拒绝策略,我们可以在任务满了之后,拒绝执行某些任务。
public class ThreadPoolTest {
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(5);
for (int i = 0; i < 10; i++) {
executor.submit(() -> {
System.out.println("thread id is: " + Thread.currentThread().getId());
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
}
}
运行结果:共用5个线程
thread id is: 12
thread id is: 15
thread id is: 11
thread id is: 14
thread id is: 13
thread id is: 14
thread id is: 13
thread id is: 15
thread id is: 12
thread id is: 11
生命周期管理
高3位保存runState,低29位保存workerCount。
用一个变量去存储两个值,可避免在做相关决策时,出现不一致的情况,不必为了维护两者的一致,而占用锁资源
04 任务执行机制
1. 任务调度:
2. 任务缓冲
3. 任务申请
4. 任务拒绝
05 小结
使用线程池:
可以减少频繁创建销毁线程所占用的CPU和内存
提高相应速度
可以限制线程池可执行的最大线程数
线程池原理:核心线程池,最大线程数量,阻塞队列,拒绝策略,生命周期(运行状态+线程数量)
任务执行机制:任务调度,任务缓冲,任务申请,任务拒绝。
参考:
https://www.jianshu.com/p/7ab4ae9443b9
https://tech.meituan.com/2020/04/02/java-pooling-pratice-in-meituan.html