当前位置: 首页 > web >正文

线程池ThreadPoolExecutor 的使用

线程池创建的七大参数:
        1、corePoolSize:线程池核心线程数量,核心线程不会被回收,即使没有任务执行,也会保持空闲状态。如果线程池中的线程少于此数目,则在执行任务时创建。
        2、maximumPoolSize:当线程数量达到corePoolSize,且workQueue队列塞满任务了之后,继续创建线程,但不能超过 maximumPoolSize。
        3、keepAliveTime:超过corePoolSize之后的“临时线程”的存活时间。
        4、unit:keepAliveTime的单位。
        5、workQueue:当线程数超过corePoolSize时,新的任务会处在等待状态,并存在workQueue中,BlockingQueue是一个先进先出的阻塞式队列实现,workQueue有以下几种实现:

            (1)、ArrayBlockingQueue  基于数组的有界阻塞队列,按FIFO排序。新任务进来后,会放到该队列的队尾,有界的数组可以防止资源耗尽问题。当线程池中线程数量达到corePoolSize后,再有新任务进来,则会将任务放入该队列的队尾,等待被调度。如果队列已经是满的,则创建一个新线程,如果线程数量已经达到maxPoolSize,则会执行拒绝策略。

           (2)、LinkedBlockingQuene基于链表的无界阻塞队列(其实最大容量为Interger.MAX),按照FIFO排序。由于该队列的近似无界性,当线程池中线程数量达到corePoolSize后,再有新任务进来,会一直存入该队列,而不会去创建新线程直到maxPoolSize,因此使用该工作队列时,参数maxPoolSize其实是不起作用的。

          (3)、SynchronousQuene一个不缓存任务的阻塞队列,生产者放入一个任务必须等到消费者取出这个任务。也就是说新任务进来时,不会缓存,而是直接被调度执行该任务,如果没有可用线程,则创建新线程,如果线程数量达到maxPoolSize,则执行拒绝策略。

          (4)、PriorityBlockingQueue 具有优先级的无界阻塞队列,优先级通过参数Comparator实现。

           ArrayBlockingQueue和PriorityBlockingQueue一般很少使用

        6、threadFactory:创建线程的工厂类,通常我们会自定义一个threadFactory设置线程的名称,这样我们就可以知道线程是由哪个工厂类创建的,可以快速定位。
        7、handler:线程池执行拒绝策略,当线程数量达到maximumPoolSize大小,并且workQueue也已经塞满了任务的情况下,线程池会调用handler拒绝策略来处理请求。

ThreadPoolExecutor 的使用示例:
public class HelloThreadPool {static class Task implements Runnable {private int i;public Task(int i) {this.i = i;}@Overridepublic void run() {System.out.println(Thread.currentThread().getName() + " Task " + i);try {System.in.read();//TimeUnit.MILLISECONDS.sleep(500);} catch (Exception e) {e.printStackTrace();}}@Overridepublic String toString() {return "Task{" +"i=" + i +'}';}}public static void main(String[] args) {ThreadPoolExecutor tpe = new ThreadPoolExecutor(3, 5,5, TimeUnit.SECONDS,    //5 秒內沒有任务要处理,非核心线程释放掉/**队列中最多能存入的任务数量*   当所有的核心线程都在处理任务的时候,新进来的任务将放入队列中,如果队列中放满了,则新建额外的线程处理,总线程数量不能超过maximumPoolSize*/new ArrayBlockingQueue<Runnable>(4),Executors.defaultThreadFactory(),//  默认的线程工厂,通过 new Thread 产生线程/**四个拒绝策略:* AbortPolicy:为线程池默认的拒绝策略,该策略直接抛异常处理。* DiscardPolicy:直接抛弃不处理。* DiscardOldestPolicy:丢弃队列中最老的任务。* CallerRunsPolicy:将任务分配给当前执行 execute 的方法线程来处理,如这个调用方法中表示 main方法主线程。*/new ThreadPoolExecutor.CallerRunsPolicy());//创建10个线程,核心线程限制性,然后放入等待队列,等待队列放满后再新建线程for (int i = 0; i < 10; i++) {tpe.execute(new Task(i));}System.out.println(tpe.getQueue());tpe.execute(new Task(100));System.out.println(tpe.getQueue());tpe.shutdown();}

        线程在使用过程中新创建的值会放在threadLocalMap中,threadLocalMap是以threadlocal作为键、value作为值来存储的,对于普通线程当线程执行结束后线程被销毁、threadLocalMap也随之被清空;

        但是对于线程池,线程执行完成后thread并不会被销毁,会将threadlocal置为空来保证同一个thread执行不同任务的数据安全,但是threadlocal被置为空后value还在,等到新的任务执行时也会产生threadLocalMap,不断的累计这些value值可能会导致内存溢出;

        线程池防止内存溢出的解决办法是执行完一个任务后调用threadlocal的remove方法,清空这些value值;    

线程池的源码解读:

       从上面代码中的 tpe.execute(new Task(i)) 点进去:

addWorker方法解读:

可参考:【精选】线程池的设计与原理解析(三)之---addWorker()方法-CSDN博客

       

        然后是创建一个任务线程,并将线程放入任务队列中,更新线程池中线程数量,如果添加到线程池失败则移除线程、线程数量减1

线程执行方法 runWorker 说明:

        线程通过while从任务队列中获取任务执行,一直到没有可执行任务(线程池中没有任务或线程池执行了关闭方法)或执行任务出现异常跳出while循环,然后执行finally中的processWorkerExit方法,processWorkerExit 有两种逻辑异常退出和正常退出;

             异常退出:线程执行过程中出现异常,更新可用线程数减1 ,在线程池中移除这个线程,然后在最后再添加一个线程到线程池中

             正常退出:没有可执行任务,先移除这个线程,然后判断线程池中的线程数是否大于核心线程数,如果不满足则创建一个新的线程到线程池中

      线程本身没有是否核心线程这个属性,只要线程没有可执行任务时就会调用processWorkerExit方法,然后就会被销毁,线程池中最后也只会保留核心数量的线程,而不管这些线程是刚开始的核心线程还是后面新建的线程;

getTask方法说明:
       poll方法阻塞一定时间
       take方法一直阻塞      
processWorkerExit方法说明:

http://www.xdnf.cn/news/11676.html

相关文章:

  • 排序算法总结——归并排序
  • 信号强度(RSSI)知识整理
  • AVPlayer 播放在线视频和本地文件的设置区别
  • Hydra(九头蛇)工具使用(非常详细)零基础入门到精通,收藏这一篇就够了!!!
  • linux 下理解文件系统的inode
  • SM2——适用于前后端(java+vue)公用的SM2国密加解密传输
  • MXNet 相关函数详解
  • 电脑安装ubuntu系统详细教程
  • JDK安装教程
  • 000-搭建Gitea-自己的git服务器
  • SSM框架讲解(史上最详细的文章)
  • scrapy框架--快速了解
  • IDEA配置JavaFX
  • (一)PaddlePaddle(深度学习框架)的搭建、使用
  • DFS(深度优先搜索)入门介绍
  • shuffle
  • JSP详细基础教学
  • Python网络爬虫之Xpath详解
  • Python的包安装工具——pip命令大全
  • netstat详解
  • Linux-文件查找find命令
  • Echarts热力图配置项,一篇文章告诉你。
  • 神仙级Python入门教程(非常详细),从零基础入门到精通,看这篇就够了
  • 一文详细说明spring cloud和Spring Cloud Alibaba的各自组件以及联系和区别
  • Validate表单验证插件之常用参数介绍
  • 网关 GateWay 的使用详解、路由、过滤器、跨域配置
  • 神经网络(NN)网络构建及模型算法介绍
  • 从计网的角度讲明白什么是网关
  • Apollo入门使用手册
  • Java资源大全(更新中)