java 线程池 ---- ThreadPoolExecutor 类

Posted 黄光跃

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java 线程池 ---- ThreadPoolExecutor 类相关的知识,希望对你有一定的参考价值。

执行流程

  1, 创建线程池后, 默认不会创建线程, 等到有任务带来才创建线程, 即一个线程处理一个任务
  2, 当线程数量达到核心线程数时, 任务放进队列, 如果放入队列失败, 创建新线程处理任务(此时线程池线程数大于核心线程数)
  3, 如果线程数大于最大线程数, 执行拒绝策略处理任务

构造方法

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

参数解释

  corePoolSize: 核心线程数, 当线程数量达到 corePoolSize 后, 后面的任务将会被放进队列排队

  maximumPoolSize: 能创建的最大线程数

  keepAliveTime: 当线程数量大于核心线程数量的时候生效, 表示空闲时间, 一旦超过这个时间, 该线程将被销毁

  unit: 超时单位, TimeUtil 规定, 有7中静态成员变量

  workQueue: 一个阻塞队列, 保存等待执行的任务

    ArrayBlockingQueue: 基于数组实现的先进先出队列, 创建时必须指定大小, 当需要处理的任务大于队列的大小时, 拒绝策略生效
    LinkedBlockingQueue: 基于链表的先进先出队列, 创建时可选指定大小, 如果不指定默认是 Integer.MAX_VALUE(推荐使用)
    synchronousQueue: 不保存任务, 直接新建一个线程来执行新来的任务

  threadFactory: 线程工场, 用于创建线程

  handler: 拒绝策略

    ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常, 这是默认的方式
    ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。
    ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)
    ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务

常用方法

  execute(): 向线程池提交任务
  submit(): 也是向线程池提交任务, 能获取到线程的返回值
  shutdown(): 关闭线程池, 停止接收新任务, 等待处理完已经接收的任务后关闭
  shutdownNow(): 关闭线程池, 立即关闭, 打断正在处理的任务, 清空队列, 返回未处理的任务
  getQueue().size(): 队列中等待的任务数量
  getPoolSize(): 线程数量
  getCompletedTaskCount(): 已经处理的任务数量

示例

class MyThread implements Runnable{
    private int index;

    public MyThread(int index){
        this.index = index;
    }

    @Override
    public void run() {
        System.out.println("处理任务:" + index);
    }
}
public class Test1 {
    public static void main(String[] args){
        
        // 任务队列
        ArrayBlockingQueue<Runnable> queue = new ArrayBlockingQueue<>(5);
        // 拒绝策略
        ThreadPoolExecutor.DiscardPolicy handler = new ThreadPoolExecutor.DiscardPolicy();

        // 创建线程池
        ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 3, 100, TimeUnit.MICROSECONDS, queue, handler);

        // 1. 任打印 1-15, 每次打印就是一个任务, 有 15 个任务
        // 2. 15 个任务, 每次只能处理 2 个, 因为 corePoolSize 是 2; 所以将会有任务进行排队
        for (int i = 0; i < 15; i++){
            MyThread myThread = new MyThread(i);
            // 1. 每个队列只能放 5 个任务, 因为队列指定的数量是 5; 所以会有任务放入不成功, 将会创建新线程
            // 2. 最大线程数是 3, 因为 maximumPoolSize 是 3; 所以会有任务将被拒绝
            // 3. 这里使用的拒绝策略是: 直接抛弃, 并且不抛出异常
            executor.execute(myThread);
        }
        // 关闭服务
        executor.shutdown();

    }
}

 














以上是关于java 线程池 ---- ThreadPoolExecutor 类的主要内容,如果未能解决你的问题,请参考以下文章

线程池的理解

高并发通过ThreadPoolExecutor类的源码深度解析线程池执行任务的核心流程

高并发通过ThreadPoolExecutor类的源码深度解析线程池执行任务的核心流程

关于java线程池

java 如何获得线程池中正在执行的线程数?

Java线程池