• 线程池原理解析


    参考博客

    一、什么时候使用线程池

      单个任务处理时间比较短,且需要处理的任务数量很大。

    二、线程池优势

      1.重用存在的线程,减少线程创建、消亡的开销,提高性能。

      2.提高响应速度,当任务到达时,任务可以不需要等到线程创建就能立即执行。

      3.提高线程的可管理型,可以统一分配、调优和监控。

    三、线程池运行机制

    1. 核心参数

    1 int corePoolSize,           //核心池的大小,核心线程一直会存在,即使没有任务
    2 int maximumPoolSize,             //池中允许的最大线程数,这个参数表示了线程池中最多能创建的线程数量
    3 long keepAliveTime,         //当线程数大于corePoolSize时,终止前多余的空闲线程等待新任务的最长时间
    4 TimeUnit unit,            //keepAliveTime时间单位
    5 BlockingQueue<Runnable> workQueue, //存储还没来得及执行的任务 阻塞队列 有界 | 无界
    6 ThreadFactory threadFactory,    //执行程序创建新线程时使用的工厂
    7 RejectedExecutionHandler handler   //由于超出线程范围和队列容量而使执行被阻塞时所使用的处理程序

    2. 运行机制----优先使用核心线程,其次阻塞队列,最后非核心线程(临时工)

    1 1 判断任务是否为空
    2 2 池中线程数小于corePoolSize,新任务都不排队而是直接添加新线程
    3 3 池中线程数大于等于corePoolSize,workQueue未满,首选将新任务加入workQueue而不是添加新线程
    4 4 池中线程数大于等于corePoolSize,workQueue已满,但是线程数小于maximumPoolSize,添加新的线程来处理被添加的任务
    5 5 池中线程数大于大于corePoolSize,workQueue已满,并且线程数大于等于maximumPoolSize,新任务被拒
    6 6 绝,使用handler处理被拒绝的任务

    3. 阻塞队列

      阻塞队列:无论并发有多高,永远只有一个线程能够进行队列的入队和出队操作。线程安全。分为有界和无界。队列满,只能进行出队操作,入队阻塞。队列空,只能进行入队操作,出队阻塞。

    1 ArrayBlockingQueue:是一个基于数组结构的有界阻塞队列,此队列按 FIFO(先进先出)原则对元素进行排序。
    2 LinkedBlockingQueue:一个基于链表结构的阻塞队列,此队列按FIFO (先进先出) 排序元素,吞吐量通常要高于ArrayBlockingQueue。静态工厂方法Executors.newFixedThreadPool()使用了这个队列
    3 synchronousQueue:这个队列比较特殊,它不会保存提交的任务,而是将直接新建一个线程来执行新来的任务。
    4 PriorityBlockingQueue:一个具有优先级的无限阻塞队列。
    有界队列

    1.初始的poolSize < corePoolSize,提交的runnable任务,会直接做为new一个Thread的参数,立马执行 。

    2.当提交的任务数超过了corePoolSize,会将当前的runable提交到一个block queue中。

    3.有界队列满了之后,如果poolSize < maximumPoolsize时,会尝试new 一个Thread的进行救急处理,立马执行对应的runnable任务。

    4.如果3中也无法处理了,就会走到第四步执行reject操作。

    无界队列
    与有界队列相比,除非系统资源耗尽,否则无界的任务队列不存在任务入队失败的情况。当有新的任务到来,系统的线程数小于corePoolSize时,则新建线程执行任务。当达到corePoolSize后,就不会继续增加,若后续仍有新的任务加入,而没有空闲的线程资源,则任务直接进入队列等待。若任务创建和处理的速度差异很大,无界队列会保持快速增长,直到耗尽系统内存。


    4. 拒绝策略

    1 ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。 
    2 ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。 
    3 ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)
    4 ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务 

    5. 主要方法

    1 execute() 以向线程池提交一个任务,交由线程池去执行。
    2 submit() 这个方法也是用来向线程池提交任务的,但是它和execute()方法不同,它能够返回任务执行的结果,去看submit()方法的实现,会发现它实际上还是调用的execute()方法,只不过它利用了Future来获取任务执行结果。
    3 shutdown() 和 shutdownNow() 是用来关闭线程池的
    创建线程池之后,线程池中是没有线程的,需要提交任务后才会创建线程。在实际中如果需要线程池创建之后立即创建线程,可以通过以下两个方法办到:
    4 prestartCoreThread():初始化一个核心线程;默认情况下,
    5 prestartAllCoreThreads():初始化所有核心线程

     excute()&submit():https://www.cnblogs.com/by-my-blog/p/10779333.html

    6. 线程池五种状态

     

    1 1.Running(111)能接受新任务,能处理已添加的任务。
    2 2.Shutdown(000 在Running状态执行shutdown())不接受新任务,能处理已添加的任务。
    3 3.Stop (001,在Running状态执行shutdownNow()) 不接受新任务,不处理已添加的任务,并且中断当前正在处理的任务。
    4 4.Tidying (010,Shutdown状态:阻塞队列为空,线程池中工作线程数量为0   /   Stop状态:线程池中的工作线程数量为0)
    5     所有的任务已经终止,ctl记录的‘任务数量’为0,ctl负责记录线程池的运行状态和活动线程数量。
    6 5.Terminated (011,Tidying状态执行terminated())线程池彻底终止,则线程转变为Terminated状态。

     7. 线程池种类

    1 newCachedThreadPool:创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
    2 newFixedThreadPool:创建一个可重用固定线程数的线程池
    3 newSingleThreadExecutor:创建一个使用单个 worker 线程的 Executor
    4 newScheduleThreadPool: 创建一个线程池,它可安排在给定延迟后运行命令或者定期地执行。
    5 newSingleThreadScheduledExecutor:创建一个单线程执行程序,它可安排在给定延迟后运行命令或者定期地执行。
    时间轮 VS 优先队列

     8. 核心线程数设置

      一般说来,大家认为线程池的大小经验值应该这样设置:(其中N为CPU的个数)
      如果是CPU密集型应用,则线程池大小设置为N+1
      如果是IO密集型应用,则线程池大小设置为2N+1
      如果一台服务器上只部署这一个应用并且只有这一个线程池,那么这种估算或许合理,具体还需自行测试验证。
      但是,IO优化中,这样的估算公式可能更适合:
        最佳线程数目 = ((线程等待时间+线程CPU时间)/线程CPU时间 )* CPU数目
      因为很显然,线程等待时间所占比例越高,需要越多线程。线程CPU时间所占比例越高,需要越少线程。
      下面举个例子:比如平均每个线程CPU运行时间为0.5s,而线程等待时间(非CPU运行时间,比如IO)为1.5s,CPU核心数为8,那么根据上面这个公式估算得到:((0.5+1.5)/0.5)*8=32。这个公式进一步转化为:最佳线程数目 = (线程等待时间与线程CPU时间之比 + 1)* CPU数目

  • 相关阅读:
    Spring实现AOP的4种方式(转)
    【转】一个不错的eclipse反编译插件
    spring配置事务
    使用XFire+Spring构建Web Service(一)——helloWorld篇
    WebService到底是什么?(转)
    ContextLoaderListener作用详解(转)
    SVN检出资源文件
    ExtJS4.2学习(21)动态菜单与表格数据展示操作总结篇2
    WP8_当滚动到滚动条的70%时,自动加载数据效果实现
    WP8__从windowsphone app store 中根据app id获取应用的相关信息(下载网址及图片id等)
  • 原文地址:https://www.cnblogs.com/qmillet/p/12465789.html
Copyright © 2020-2023  润新知