zoukankan      html  css  js  c++  java
  • 线程池使用总结

    线程池使用总结

    Excutors工厂类

    为了更好的控制更多的多线程,JDK提供返回一个固定数量的线程池。

    方法:

    • newFixedThreadPool()方法:
      改方法返回一个固定数量的线程池,改方法的线程数,始终不变,当一个任务提交时,若线程池空闲,则立即执行,若没有,则会被暂缓在一个任务队列中等待有空闲的线程去执行。
    • newSingleThreadPool()方法
      创建一个单例的线程池,若空闲则执行,若没有空闲线程则暂缓在任务队列中
    • newCachedThreadPool()方法
      返回一个可根据实际情况调整线程个数的线程池,不限制最大线程数量,若有任务,则创建线程,若无任务则不创建线程,如果没有任务则线程会在60s后自动回收。
    • newScheduledThreadPool()方法:该方法返回一个ScheduledExcutorService对象,但该线程池可以指定线程的数量。

    自定义线程池-ThreadPoolExecutors

    • 自定义线程池:ThreadPoolExecutor

    线程池相关参数的配置

     ThreadPoolExecutor(int corePoolSize, //核心线程数,线程初始化就会被创建
                                  int maximumPoolSize, //线程池最大线程数,无界队列时,不起作用
                                  long keepAliveTime, //线程的存活时间
                                  TimeUnit unit,      //时间的单位
                                  BlockingQueue<Runnable> workQueue, //阻塞队列,使用无界队列时,拒绝策略无用
                                  ThreadFactory threadFactory,//theadFactory 线程工厂,用于获取一个新的线程,然后把该线程投递到线程池里面去
                                  RejectedExecutionHandler handler) //拒绝策略
    

    1.当设置为有界队列时:

    a 若有新的任务需要执行,如果线程实际数小于coreThread,则先创建线程

    b.若大于coreSize,则会加入任务队列

    c.若队列已满,则在不大于maxinumPoolsize的情况下创建新的线程

    d.若线程数不大于maxinumPoolSize会执行拒绝策略

    2.当为无界队列时

    a.maximumPoolSize不起作用,也没有拒绝策略

    b.若有新的任务需要执行,如果线程实际数小于coreThread,则先创建线程

    c.若大于coreSize,则会加入任务队列,同时创建新的线程。

    如何使用好线程池?

    • 线程个数大小的设置
    • 线程池相关参数的配置
    • 利用Hook嵌入你的行为
    • 线程池的关闭

    线程池数量的设置

    计算机密集型

    应用需要非常多的CPU计算资源,避免过多的线程上下文切换

    线程数 = CPU核数+1,已可以设置为CPU核数*2,还要看JDK的版本以及CPU配置(服务器的CPU有超线程)

    IO密集型

    Web应用,涉及到大量的网络传输,不仅如此,与数据库,与缓存间的交互也涉及到IO,一旦发生IO,线程就会处于等待状态,当IO结束后,数据准备好后,线程才会继续执行。对于IO密集型的应用,我们可以多设置线程池中线程的数量,这样就能让等待IO的这段时间内,线程可以去做其它事,提高并发处理效率。线程上下文切换数有代价的

    线程数 = CPU核数/(1-阻塞系数) 这个阻塞系数一般为0.8~0.9之间。

    套用公司:对于双核CPU来说,比较理想的线程数就是20,当然这不是绝对的,需要根据实际情况以及实际业务来调整:final int poolSIze = (int)(copCore/(1-0.9))

    线程池相关参数如何配置?

    • 高压线:
      • 我们使用线程池的时候都不要选择没有上限限制的配置项
    • 第一 我们不要去使用没有上限的线程池和设置无界队列!
    • 比如,newCachedThreadPool的设置与无界队列因为某些不可预期的情况,线程池会出现系统异常,导致线程暴增的情况或者任务队列或者任务队列不断膨胀,内存耗尽导致系统崩溃。我们建议自定义线程池来避免改问题,这是在使用线程池的首要选择。小心无大错,千万别过度自信。
    • 第二 合理设置线程数量、和线程空闲回收时间,根据具体的任务执行周期和时间去设定,避免频繁的回收和创建,虽然我们使用线程池的目的是为了提升系统性能和吞吐量,但是也要考虑下系统的稳定性,不然出现不可预期问题会很麻!
    • 第三,根据实际场景,选择适用于自己的拒绝策略。进行补偿,不要乱用JDK支持的自动补偿机制~尽量采用自定义的拒绝策略去进行兜底!

    利用Hook去嵌入你的行为

    • 利用Hook,留下线程池执行的执行轨迹
    • ThreadPoolExcutor提供了protected类型可以被覆盖的钩子方法,运行用户在执行任务之前或执行之后做一些事情。我们可以通过它来实现比如初始化ThreadLocal、收集统计信息、如记录日志等操作,这类Hook如BeforeExcute和afterExecute。另外还有一个Hook可以用来在任务呗执行完的时候让用户插入逻辑,如reminated。
    • Hook方法执行失败,则内部的工作线程的执行将会失败或者中断。

    关闭线程池

    • 内容当线程池不在被引用并且工作线程数为0的时候,线程池将被终止。我们也可以调用shutdown来手动终止线程池。如果我们忘记调用shutdown,为了让线程资源被释放,我们还可以使用keepAliveTime和allowShutdownHook方法,手工去调用线程池的关闭方法!
    • 最稳妥的方式是使用虚拟机Runtime.getRuntime().addShutdownHook方法,手动去调用线程池关闭方法。
  • 相关阅读:
    JS正则改变字符之间文字
    MySQL 实现字符串换行
    日志AOP的实现
    mysql in和exists性能比较和使用
    【微服务】使用spring cloud搭建微服务框架,整理学习资料
    专注细节,回归本质,成败在微小之间
    【前端】 在前端利用数学函数知识+box-shadow解波浪图形
    互联网行业个人精进指南
    拒绝洗脑式广告,无限重复洗脑式广告应该受到谴责。怎么有效抵制这类广告?
    【redis】redis应用场景,缓存的各种问题
  • 原文地址:https://www.cnblogs.com/renqiqiang/p/10129352.html
Copyright © 2011-2022 走看看