• 线程池详解


    手动创建线程池方法及参数

    //手动创建线程池
    ThreadPoolExecutor executor = new ThreadPoolExecutor(2,5,
            3,TimeUnit.SECONDS,
            new LinkedBlockingQueue<>(),
            new ThreadPoolExecutor.AbortPolicy());
    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue workQueue,
                              RejectedExecutionHandler handler) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), handler);
    }

    一、线程池构造方法的参数

    二、添加线程的规则

    三、任务存储工作队列

     四、手动创建线程池

     1.newFixedThreadPool 固定线程池(核心线程数=最大线程数,队列满后无法增加线程)

    ExecutorService executorService = Executors.newFixedThreadPool(5);
    
    public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue());
    }

      创建一个线程池,指定线程数量5,默认使用无界队列LinkedBlockingQueue,大量任务执行未完成的情况下,可能会造成OOM内存溢出异常。

     2.newSingleThreadExecutor  单一线程池

    public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue()));
    }

    与newFixedThreadPool类似,只是线程数量固定为1,同样使用无界队列,大量任务同样造成OOM内存溢出正常。

    3.newCachedThreadPool 可缓存线程池(可自动回收空闲线程,队列没有容量)

    public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue());
    }

     无界线程数量,直接交换队列,线程存活默认60s自动回收,可能会创建数量特别多的线程导致OOM内存溢出异常。

    4.newScheduledThreadPool 定时线程池(周期性任务执行,使用延迟队列DelayedWorkQueue)

    public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
        return new ScheduledThreadPoolExecutor(corePoolSize);
    }
    public ScheduledThreadPoolExecutor(int corePoolSize) {
        super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
              new DelayedWorkQueue());
    }

    如:

    ScheduledExecutorService threadPool = Executors.newScheduledThreadPool(10);
    //10s后开始执行一次任务,需手动关闭
    threadPool.schedule(new Task(),10, TimeUnit.SECONDS);
    //第一次1s后执行,后面每3s执行一次
    threadPool.scheduleAtFixedRate(new Task(),1,3,TimeUnit.SECONDS);

    五、线程池线程数量设置多少合适(最佳:不同程序做不同的压测得出最优线程数量)

    六、停止线程池的正确方法

    1.shutdown 存量任务和当前任务执行完毕后线程关闭,不再接收新任务

    2.isShutdown获取当前线程池的开启关闭状态

    3.isTerminated获取线程池是否真正已停止

    4.awaitTermination监测时间范围内线程是否运行完毕

    5.shutdownNow 立刻停止线程

    七、线程池的暂停和恢复

    钩子函数beforeExecute

    八、 线程池的实现原理,源码分析

    线程池的组成部分:线程池管理器、工作线程、任务队列、任务接口(Task)

    runWorker只要Runnable任务不为空就会一直执行

    九、线程池任务的拒绝策略

    拒绝策略提供顶级接口 RejectedExecutionHandler ,其中方法 rejectedExecution 即定制具体的拒绝策略的执行逻辑。
    jdk默认提供了四种拒绝策略:

    • AbortPolicy - 丢弃任务,并抛出拒绝执行 RejectedExecutionException 异常信息。线程池默认的拒绝策略。必须处理好抛出的异常,否则会打断当前的执行流程,影响后续的任务执行
    • CallerRunsPolicy - 当触发拒绝策略,只要线程池没有关闭的话,则使用调用线程直接运行任务。一般并发比较小,性能要求不高,不允许失败。但是,由于调用者自己运行任务,如果任务提交速度过快,可能导致程序阻塞,性能效率上必然的损失较大
    • DiscardPolicy - 直接丢弃,其他啥都没有
    • DiscardOldestPolicy - 当触发拒绝策略,只要线程池没有关闭的话,丢弃阻塞队列 workQueue 中最老的一个任务,并将新任务加入

    十、线程池状态和使用注意

    注意: 

    手动创建线程池,避免风险;线程数设置合理;考虑多个线程池间的影响

     

  • 相关阅读:
    C++程序练习
    【Android】App开发-控件篇
    Linux:进程控制
    Python学习笔记(22)-Python框架22-PyQt框架使用(常用控件)
    【设计模式】四、工厂模式
    Leetcode 278. First Bad Version
    MySQL索引的底层数据结构原理剖析(二叉树、 红黑树、Hash、B-Tree、B+Tree)
    秋招每日一题T14——将矩阵按对角线排序
    一款可插拔的AM335X工控模块板载wifi模块
    FFmpeg入门详解之8:YUV Player简介
  • 原文地址:https://blog.csdn.net/TurboAnho/article/details/127507969