• JAVA Executor(线程池)框架


    一、Executor概述

    为更好控制线程,jdk提供一套线程管理框架Executor,帮助开发人员有效地进行线程控制。它们都位于java.util.concurrent包中,是jdk并发包的核心。其中有个比较重要的类:Executors,他扮演着线程工厂的角色,我们可以通过Executors创建特定功能的线程池。

    二、Executors创建线程的方法

    newFixedThreadPool()方法:返回一个固定数量的线程池,线程数始终不变,当有一个任务提交时,若线程池中空闲,则立即执行;若没有,则会被暂缓在一个任务队列里等待有空闲的线程去执行(队列是无界队列,无限缓存线程数)

    newSingleThreadPoolExecutor()方法:创建一个线程的线程池,若空闲则执行,若没空闲线程则暂缓在任务队列(队列是无界队列,无限缓存线程数)

    newCachedThreadPool():返回一个可根据实际情况调整线程个数的线程池,不限制最大线程数量,若有任务则创建线程执行,若无任务则不创建线程,并且每个空线程会在60s后自动回收。(初始化不创建线程)

    newScheduledThreadPool():返回一个ScheduledExecutorService对象,但该线程池可以指定线程的数量(不限线程池数量),带有延迟时间的去获取线程。通常用spring的Scheduled

     这4个方法返回的都是ThreadPoolExecutor对象

    三、自定义线程池——ThreadPoolExecutor

    若Executors的工厂方法无法满足我们的需求,可以自己用ThreadPoolExecutor去创建自定义的线程池(其实Executors的工厂方法内部就是用ThreadPoolExecutor类实现的)

    (1)构造方法如下

    public ThreadPoolExecutor(int corePoolSize,
                                  int maximumPoolSize,
                                  long keepAliveTime,
                                  TimeUnit unit,
                                  BlockingQueue<Runnable> workQueue,
                                  ThreadFactory threadFactory,
                                  RejectedExecutionHandler handler)

    corePoolSize:核心线程数

    maximumPoolSize:最大线程数

    keepAliveTime:每个线程保持活着的空闲时间数字

    unit:keepAliveTime的时间单位

    workQueue:存放线程的队列(线程超过maximumPoolSize时用到)

    threadFactory:线程工厂,主要用来创建线程

    handler:拒绝任务执行的处理器(情景:假设线程池数量最大为3,队列长度最大为2,现在有3个任务在执行未释放线程,而任务里也有2个任务在排队了,我们认为后面再来任务就可以丢弃了,这个handler处理的就是这种情况)

    有以下四种取值:
    ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。(JDK默认的拒绝策略)
    ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。
    ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)
    ThreadPoolExecutor.CallerRunsPolicy:只要线程池不关闭,该策略直接在调用者线程中,运行当前被丢弃的任务
    个人认为这4中策略不友好,最好自己定义拒绝策略,实现RejectedExecutionHandler接口

    构造方法详细解读:

    a.构造方法的队列类型比较关键

    如果使用有界队列

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

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

    3).有界队列满了之后,如果poolSize < maximumPoolsize(poolSize是在运行的线程数,不包括队列里面的线程)时,会尝试new 一个Thread的进行救急处理,立马执行对应的runnable任务。

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

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

    四、ThreadPoolExecutor的submit与excute的区别

    1.submit可以传入Callable接口的实例对象

    2.submit方法有返回值

  • 相关阅读:
    SwiftUI_2_共享绑定
    iOS_知识点_动画&绘图
    excle表格数据列前批量添加数据
    异步编程模式学习
    这不是一篇技术文档!
    lowcode
    java中如何针对系统灵活变换分割符?
    linux安装nginx
    序列化与反序列化
    Linux安装nginx star
  • 原文地址:https://www.cnblogs.com/billmiao/p/9872203.html
Copyright © 2020-2023  润新知