• [转发]对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

  • 相关阅读:
    《相约星期二》--[美]米奇·阿尔博姆
    《把信送给加西亚》--[美]阿尔伯特·哈伯德
    《少有人走的路:心智成熟的旅程》--[美]M·斯科特·派克
    《穷爸爸和富爸爸》--[美]罗伯特·清崎,[美]莱希
    Error This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. T
    C#轻量级高性能日志组件EasyLogger
    我们为何要跳槽
    Grid++Report报表工具C/S实战篇(五)
    .NET 开源Protobuf-net从入门到精通
    怎样防止ddos攻击
  • 原文地址:https://www.cnblogs.com/xiaokangk/p/12552917.html
Copyright © 2020-2023  润新知