🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# 使用线程池的好处 线程池做的工作主要是控制运行的线程的数量,处理过程中将任务放 ,然后在线程创建后启动这些任务,如果线程数量超过了最大数量超出数量的线程排队等候,等其它线程执行完毕,再从队列中取出在务来执行。 1. 降低资源的消耗 通过重复利用已经创建好的线程降低线程的创建和销毁带来的损耗 2. 提高相应速度 因为线程池中的线程数没有超过线程池的最大上限时,有的线程处于等待分配任务的状态, 当任务来时无需创建新的线程就能执行. 3. 提高线程的可管理性 线程池会对线程做优化处理, 减少创建和销毁线程带来的系统开销. # ThreadPoolExecutor ## 线程池 七大参数 ![](https://img.kancloud.cn/4c/fe/4cfeaef9cdf918042238f55b6345f3d9_796x267.png) ### corePoolSize 核心线程数 要比maximumPoolSize 小 线程池中日常用来工作的核心的线程数量 ### maximumPoolSize 最大线程数量 设置上限、控制资源,防止并发太大把资源耗尽 ### keepAliveTime 存活时间, 多久释放空闲的线程 如果当前的空闲线程数量大于corePoolSize 的数量, 超过这个时间,就会把多余的线程释放掉。释放的是大于corePoolSize 的部分,因为corePoolSize 默认是一直存在 ### TimeUnit unit 时间单位 keepAliveTime 的时间单位 ### BlockingQueue workQueue 阻塞队列 如果任务有很多,超过了核心线程数,就把过多的任务放到队列中,等线程空闲了就会去队列中取出任务进行执行。 比如传 new LinkedBlockingDeque<>(1000000) 做队列, 数量最大是 Integer 的最大值, 设置的数值太大会导致内存不够,注意设置的值要根据内存大小来进行设置 ### ThreadFactory threadFactory 线程的创建工厂 RejectedExecutionHandler handler 队列满了的处理策略(拒绝策略) 如果队列满了,按照我们指定的拒绝策略进行拒绝执行任务 ## 工作顺序(工作原理): 1. 线程池创建,来了任务才去创建线程。也可以设置直接好core数量的核心线程, 2. 线程池中有空闲线程,则直接执行该任务 3. 没有空闲线程,且当前运行的线程数少于核心线程,则创建新的线程执行该任务 4. 核心线程满了且阻塞队列未满,则将任务入队列等待线程空闲来队列获取任务 5. 阻塞队列满了,就直接开新线程执行新来的任务,最大不能超过设置的最大线程数 6. 最大线程数也满了则使用设置的拒绝策略去处理这个任务 7. 当线程空闲下来,在空闲时间超过设置的存活时间后,会释放掉非核心线程(超过设置核心线程数的线程都释放) ## 拒绝策略 AbortPolicy默认):**直接抛异常**,直接抛出RejectedExecutionException异常阻止系统正常运行。 CallerRusPlic:**谁提交谁执行**,这种就是把这个任务交于提交任务的线程执行。 "调用者运行"一种调节机制,该策略既不会抛弃任务,也不会抛出异常,而是将某些任务回退到调用者,从而降低新任务的流量。这个方案即使线程池中的资源全部耗尽,也只会降级到串行执行,不会让系统变的更糟糕。任务不让丢失推荐这个方案。 DiscardPolicy:**直接丢弃** 直接丢弃任务,不予任何处理也不抛出异常。如果允许任务丢失,这是最好的一种方案。 DiscardoldestPolicy:**直接丢弃任务队列中的头结点** 抛弃队列中等待最久的任务,然后把当前任务加入队列中尝试再次提交当前任务。 ## execute()和submit() 区别 都是向线程池提交任务,submit 有返回值,execute 没有返回值 ## 合理配置线程池 根据电脑核数配置 CPU密集型: 核数 + 1, 8核就是 设置为 9 IO密集型:IO密集型不是一直在执行任务,则应配置可能多的线程, CPU * 2 的数量 ## 死锁 死锁是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力干涉那它们都将无法推进下去,如果系统资源充足,进程的资源请求都能够得到满足,死锁出现的可能性就很低,否则就会因争夺有限的资源而陷入死锁。 ### 产生死锁的主要原因 1. 系统资源不足 2. 进程运行推进的顺序不合适 3. 资源分配不当 ### 排查 使用jdk自带命令 jps -l 查询运行中的java进程 jstack 进程编号 根据上一步的java进程,选择有问题的进程编号查询进程异常信息