线程池
-
Java 线程池Java的线程实现基本都是内核级线程,和内核线程是一一对应的,所以创建线程就需要在用户态和内核态切换,资源消耗比较大,一种比较好的解决方式就是线程的重复利用,通过线程池缓存一批线程来重复使用,降低消耗。 所以线程池也像一个缓存管理器,只是比普通的缓存稍微复杂一点,实现了更精细化的管理。
-
Java 线程池使用
-
Java中有4个自带的线程池,但是要么会堆积请求,要么创建大量线程,会导致OOM, 所以不建议用。
-
使用自定义的线程池,需要了解coreSize, MaxSize, QueueSize的关系,并了解他们之前的先后顺序。 core -> queue -> max
-
重写线程池添加规则core -> queue -> max这套规则,适用于CPU密集型,但对于web应用来说,大量的操作应该是和数据库或者其他web服务的交互,在核心线程满了之后,应该是允许有一定的并发,core -> max -> queue这种,更适合IO密集型。所以在项目优化中,会重写Java线程池的这套逻辑, 在核心线程满了之后, 先扩充到最大线程数, 等到了最大线程后,再考虑用队列来缓存。
-
动态修改线程池大小在项目中,我们定义一个线程池,核心线程数和最大线程数的设置,会有一些经验主义,可能不是最优的,所以需要在项目运行过程中,不断观察并发数,线程数,CPU, 内存的关系,争取达到最优,Java的线程池提供了setCorePoolSize方法,可以在运行时修改核心线程数,具体参考美团
-
自动修改线程池大小美团的做法是通过手动修改配置系统实现,而自动修改的意思是指,通过获取JVM,操作系统的资源比如CPU,内存等资源,并监控线程池队列的积压长度,动态调整线程池的线程数, 规则可以自定义,比如: CPU利用率小于60%, 线程队列已经占用70%, 则适当扩充最大线程数。 如果 CPU 大于 80%,则缩小线程数。
-
协程-用户态线程Java线程和内核比例是1:1,一个内核态线程映射一个用户态线程, 而使用协程可以达到M:N, 即M个内核态线程,对应N个用户态线程, M < N, 落地参考Quasar, 本质是通过字节码修改技术,在方法调用时保存调用信息,然后通过Scheduler, 将Fiber调度到具体线程上。