zoukankan      html  css  js  c++  java
  • [转发]对ThreadPoolExecutor初识

    知识点提前预知:

    Java.util.concurrent.ThreadPoolExecutor类是ExecutorSerivce接口的具体实现。ThreadPoolExecutor使用线程池中的一个线程来执行给定的任务(Runnable或者Runnable)。
    Executor是接口 只能使用execute。
    ThreadPoolExecutor是实现其他线程池的核心。(ThreadPoolExecutor里面包含execute submit)
    一、预定义线程池

    FixedThreadPool
    public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads,
    0L, TimeUnit.MILLISECONDS,
    new LinkedBlockingQueue<Runnable>());
    }
    corePoolSize与maximumPoolSize相等,即其线程全为核心线程,是一个固定大小的线程池,是其优势;
    keepAliveTime = 0 该参数默认对核心线程无效,而FixedThreadPool全部为核心线程;
    workQueue 为LinkedBlockingQueue(无界阻塞队列),队列最大值为Integer.MAX_VALUE。如果任务提交速度持续大余任务处理速度,会造成队列大量阻塞。因为队列很大,很有可能在拒绝策略前,内存溢出。是其劣势;
    FixedThreadPool的任务执行是无序的;
    适用场景:可用于Web服务瞬时削峰,但需注意长时间持续高峰情况造成的队列阻塞。

    CachedThreadPool
    public static ExecutorService newCachedThreadPool() {
    return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
    60L, TimeUnit.SECONDS,
    new SynchronousQueue<Runnable>());
    }
    corePoolSize = 0,maximumPoolSize = Integer.MAX_VALUE,即线程数量几乎无限制;
    keepAliveTime = 60s,线程空闲60s后自动结束。
    workQueue 为 SynchronousQueue 同步队列,这个队列类似于一个接力棒,入队出队必须同时传递,因为CachedThreadPool线程创建无限制,不会有队列等待,所以使用SynchronousQueue;
    适用场景:快速处理大量耗时较短的任务,如Netty的NIO接受请求时,可使用CachedThreadPool。

    SingleThreadExecutor
    public static ExecutorService newSingleThreadExecutor() {
    return new FinalizableDelegatedExecutorService
    (new ThreadPoolExecutor(1, 1,
    0L, TimeUnit.MILLISECONDS,
    new LinkedBlockingQueue<Runnable>()));
    }
    咋一瞅,不就是newFixedThreadPool(1)吗?定眼一看,这里多了一层FinalizableDelegatedExecutorService包装,这一层有什么用呢,写个dome来解释一下:

    public static void main(String[] args) {
    ExecutorService fixedExecutorService = Executors.newFixedThreadPool(1);
    ThreadPoolExecutor threadPoolExecutor = (ThreadPoolExecutor) fixedExecutorService;
    System.out.println(threadPoolExecutor.getMaximumPoolSize());
    threadPoolExecutor.setCorePoolSize(8);

    ExecutorService singleExecutorService = Executors.newSingleThreadExecutor();
    // 运行时异常 java.lang.ClassCastException
    // ThreadPoolExecutor threadPoolExecutor2 = (ThreadPoolExecutor) singleExecutorService;
    }
    对比可以看出,FixedThreadPool可以向下转型为ThreadPoolExecutor,并对其线程池进行配置,而SingleThreadExecutor被包装后,无法成功向下转型。因此,SingleThreadExecutor被定以后,无法修改,做到了真正的Single。

    ScheduledThreadPool
    public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
    return new ScheduledThreadPoolExecutor(corePoolSize);
    }
    newScheduledThreadPool调用的是ScheduledThreadPoolExecutor的构造方法,而ScheduledThreadPoolExecutor继承了ThreadPoolExecutor,构造是还是调用了其父类的构造方法。

    public ScheduledThreadPoolExecutor(int corePoolSize) {
    super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
    new DelayedWorkQueue());
    }
     二、核心构造方法讲解 
    下面是ThreadPoolExecutor最核心的构造方法 

    构造方法参数讲解 

    参数名 作用
    corePoolSize 核心线程池大小
    maximumPoolSize 最大线程池大小
    keepAliveTime 线程池中超过corePoolSize数目的空闲线程最大存活时间;可以allowCoreThreadTimeOut(true)使得核心线程有效时间
    TimeUnit keepAliveTime时间单位
    workQueue 阻塞任务队列
    threadFactory 新建线程工厂
    RejectedExecutionHandler 当提交任务数超过maxmumPoolSize+workQueue之和时,任务会交给RejectedExecutionHandler来处理
    重点讲解: 
    其中比较容易让人误解的是:corePoolSize,maximumPoolSize,workQueue之间关系。 

    1.当线程池小于corePoolSize时,新提交任务将创建一个新线程执行任务,即使此时线程池中存在空闲线程。 
    2.当线程池达到corePoolSize时,新提交任务将被放入workQueue中,等待线程池中任务调度执行 
    3.当workQueue已满,且maximumPoolSize>corePoolSize时,新提交任务会创建新线程执行任务 
    4.当提交任务数超过maximumPoolSize时,新提交任务由RejectedExecutionHandler处理 
    5.当线程池中超过corePoolSize线程,空闲时间达到keepAliveTime时,关闭空闲线程 
    6.当设置allowCoreThreadTimeOut(true)时,线程池中corePoolSize线程空闲时间达到keepAliveTime也将关闭 
    线程管理机制图示: 


     

    BlockingQueue是接口,用来存储runnable对象 
     

    ArrayBlockingQueue   LinkedBlockingQueue  PriorityBlockingQueue

    ArrayBlockingQueue   :如果有新的线程进来线程池池,当前线程数目少于corePoolSize则会自动创建新的线程对象,当实质线程数目等于corePoolSize则将任务加入等待序列里面,当等待序列填充满后,创建新线程,当线程数量达到maxcorePoolSize时候执行拒绝策略。大于corePoolSize的线程是有生命期限的。ArrayBlockingQueue有界的等待队列(无序)

    LinkedBlockingQueue与ArrayBlockingQueue   ,它是无界的,直到消耗完内存为止。

    PriorityBlockingQueue有优先队列的 一般来说是先进先出。

    JDK内置了四种拒绝策略:

    1、AbortPolicy策略

    该策略直接抛出异常,阻止系统工作

    2、CallerRunsPolicy策略

    只要线程池未关闭,该策略直接在调用者线程中运行当前被丢弃的任务。显然这样不会真的丢弃任务,但是,调用者线程性能可能急剧下降。

    3、DiscardOledestPolicy策略

    丢弃最老的一个请求任务,也就是丢弃一个即将被执行的任务,并尝试再次提交当前任务。

    4、DiscardPolicy策略

    默默的丢弃无法处理的任务,不予任何处理。

    扩展RejectedExecutioHandler接口,自定义拒绝策略

    先看下RejectedExecutionHandler接口吧:

    public interfaceRejectedExecutionHandler{

        voidrejectedExecution(Runnable r,ThreadPoolExecutor executor);

    }
    ————————————————
    原文链接:https://blog.csdn.net/HNUST_LIZEMING/article/details/89005453

  • 相关阅读:
    html 上传图片前预览
    php获取当月天数及当月第一天及最后一天、上月第一天及最后一天实现方法
    php 计算 pdf文件页数
    php 获取半年内每个月的订单数量, 总价, 月份
    php 获取两个数组之间不同的值
    小程序支付功能
    关于nginx的Job for nginx.service failed because the control process exited with error code.错误
    linux 安装 Apollo
    MongoDB待续。。。
    ABP vNext...待续
  • 原文地址:https://www.cnblogs.com/xiaokangk/p/12552917.html
Copyright © 2011-2022 走看看