线程池

作者: hcq0514 | 来源:发表于2019-09-26 19:43 被阅读0次

Executors类创建

        ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
        ExecutorService fixedThreadPool = Executors.newFixedThreadPool(5);
        ExecutorService cachedThreadPool = Executors.newCachedThreadPool();

这种方式是jdk自带的创建线程池的方式,阿里的规范里是不推荐这样创建的

线程池不允许使用Executors去创建,而是通过ThreadPoolExecutor的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。 说明:Executors各个方法的弊端:
1)newFixedThreadPool和newSingleThreadExecutor:
  主要问题是堆积的请求处理队列可能会耗费非常大的内存,甚至OOM。
2)newCachedThreadPool和newScheduledThreadPool:
  主要问题是线程数最大数是Integer.MAX_VALUE,可能会创建数量非常多的线程,甚至OOM。

  • Executors类创建源码(底层都是调用new ThreadPoolExecutor)


    image.png

ThreadPoolExecutor创建

  • 构建函数(7参数)
  public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {
    }
name 含义
corePoolSize 核心线程数
maximumPoolSize 最大线程数
keepAliveTime 线程池中超过 corePoolSize 数目的空闲线程最大存活时间
unit 存活时间单位
workQueue 阻塞任务队列
threadFactory 新建线程工厂
handler 拒绝策略,当请求的线程数超过maximumPoolSize+workQueue时,交过handler处理
  • 流程
  1. 当请求的线程数小于corePoolSize时,新提交任务将创建一个新线程执行任务,即使此时线程池中存在空闲线程
  2. 当请求的线程数大于corePoolSize时,会把新提交的任务存入到workQueue里面排队等待。
  3. 当请求数量到达corePoolSize+workQueue的长度时,会把此时的线程池扩容到maximumPoolSize的数量
  4. 当请求超过workQueue的长度+maximumPoolSize的长度时,会让拒绝策略RejectedExecutionHandler 来处理这些请求
  • 以银行办办业务为例
    corePoolSize相当于现在开放的窗口(假定为2),
    maximumPoolSize银行能开放的最大窗口数量(假定为5),
    workQueue 候客区(假定为3),
    比如现在只有一个顾客来的时候,直接就给他办理业务此时size=1,
    当有三个顾客来的时候,因为此时业务窗口(corePoolSize)只有2,所以有一个人得进入候客区(workQueue)排队,
    当有6个顾客来时,此时需要处理的数量已经超过了(coresize+workQueue.size),此时银行需要临时开放其他窗口来给顾客办理业务,最大可以将所有窗口都开放,及开放窗口数量最大为maximumPoolSize
    如果此时来了11个顾客,此时请求的数量已经超过了最大开放的窗口(maximumPoolSize)+候客区(workQueue),网点已经不能再容纳了,此时就把其他来办理业务的人交给RejectedExecutionHandler来处理拒绝掉
    当人越来越少时,新开放的窗口已经空闲了,如果此时空闲时间超过keepAliveTime,就让这个窗口的营业员下班,关闭这个窗口,直到最后只剩下最开始的两个窗口(corePoolSize)

四大拒绝策略(等待队列已经满了,再也塞不下新的任务,同时线程池中的线程数达到了最大线程数,无法继续为新任务服务)

  1. AbortPolicy:处理程序遭到拒绝将抛出运行时 RejectedExecutionException
  2. CallerRunsPolicy:把任务回推给线程提交方让他自己执行(例如回推给main线程),此策略提供简单的反馈控制机制,能够减缓新任务的提交速度。
  3. DiscardPolicy:不能执行的任务将被删除
  4. DiscardOldestPolicy:如果执行程序尚未关闭,则位于工作队列头部的任务将被删除,然后重试执行程序(如果再次失败,则重复此过程)

线程池配置参考

  1. CPU 密集型
    CPU 密集的意思是该任务需要大量的运算,而没有阻塞,CPU 一直全速运行。
    CPU 密集型任务尽可能的少的线程数量,一般为 CPU 核数 + 1 个线程的线程池。
  2. IO 密集型
    由于 IO 密集型任务线程并不是一直在执行任务,可以多分配一点线程数,如 CPU * 2 。
    也可以使用公式:CPU 核数 / (1 - 阻塞系数);其中阻塞系数在 0.8 ~ 0.9 之间。。

相关文章

  • java线程池

    线程VS线程池 普通线程使用 创建线程池 执行任务 执行完毕,释放线程对象 线程池 创建线程池 拿线程池线程去执行...

  • java----线程池

    什么是线程池 为什么要使用线程池 线程池的处理逻辑 如何使用线程池 如何合理配置线程池的大小 结语 什么是线程池 ...

  • Java线程池的使用

    线程类型: 固定线程 cached线程 定时线程 固定线程池使用 cache线程池使用 定时调度线程池使用

  • Spring Boot之ThreadPoolTaskExecut

    初始化线程池 corePoolSize 线程池维护线程的最少数量keepAliveSeconds 线程池维护线程...

  • 线程池

    1.线程池简介 1.1 线程池的概念 线程池就是首先创建一些线程,它们的集合称为线程池。使用线程池可以很好地提高性...

  • 多线程juc线程池

    java_basic juc线程池 创建线程池 handler是线程池拒绝策略 排队策略 线程池状态 RUNNIN...

  • ThreadPoolExecutor线程池原理以及源码分析

    线程池流程: 线程池核心类:ThreadPoolExecutor:普通的线程池ScheduledThreadPoo...

  • 线程池

    线程池 [TOC] 线程池概述 什么是线程池 为什么使用线程池 线程池的优势第一:降低资源消耗。通过重复利用已创建...

  • java 线程池使用和详解

    线程池的使用 构造方法 corePoolSize:线程池维护线程的最少数量 maximumPoolSize:线程池...

  • 线程池

    JDK线程池 为什么要用线程池 线程池为什么这么设计 线程池原理 核心线程是否能被回收 如何回收空闲线程 Tomc...

网友评论

      本文标题:线程池

      本文链接:https://www.haomeiwen.com/subject/wzdqyctx.html