线程池要点总结

387 阅读3分钟

线程池作用

如果不用线程池

  • 反复创建线程开销很大
  • 过多的线程会占用太多内存

线程池可以对线程进行统一管理,不需要反复创建线程

线程池创建

通过ThreadPoolExecutor创建

public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue) {
    this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
         Executors.defaultThreadFactory(), defaultHandler);
}

核心参数

  • corePoolSize:核心线程数
  • maximumPoolSize:最大线程数
  • keepAliveTime:非核心线程空闲存活时间
  • workQueue:存放线程任务的阻塞队列

线程池执行流程

  • 当提交一个任务,当线程数小于核心线程数corePoolSize时候,线程池会创建一个核心线程去执行

  • 如果此时核心线程数已经满了,即线程数=corePoolSize,它就会把新的任务放入阻塞队列workQueue里面等待执行

  • 如果workQueue也满了,就会判断线程数是否小于maximumPoolSize,如果小于,就会创建一个非核心线程来执行提交的任务

  • 如果maximumPoolSize也满了,那就会执行拒绝策略

几种常用的线程池

newFixedThreadPool

public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads,
                                  0L, TimeUnit.MILLISECONDS,
                                  new LinkedBlockingQueue<Runnable>());
}
  • 线程池特点

输入n个线程
核心线程数和最大线程数相同
没有空闲时间,keepAliveTime为0
阻塞队列为LinkedBlockingQueue
是一个链表结构无界的阻塞队列,默认大小integer.MAXVALUE

newCachedThreadPool

public static ExecutorService newCachedThreadPool() {
    return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                  60L, TimeUnit.SECONDS,
                                  new SynchronousQueue<Runnable>());
}
  • 线程池特点

核心线程数为0
最大线程数为integer.MAXVALUE
阻塞队列是SynchronousQueue

  • 是一个不存储元素的阻塞队列,当一个任务进入队列,另一个任务只有等该任务完成移除后才能进入,否则一直陷入阻塞

非核心线程存活时间60s
适用于并发执行大量短期任务

newSingleThreadExecutor

public static ExecutorService newSingleThreadExecutor() {
    return new FinalizableDelegatedExecutorService
        (new ThreadPoolExecutor(1, 1,
                                0L, TimeUnit.MILLISECONDS,
                                new LinkedBlockingQueue<Runnable>()));
}
  • 线程池特点

核心线程数,最大线程数为1
阻塞队列LinkedBlockingQueue
没有空闲时间
适用于串行执行任务场景,一个任务接着一个任务执行

newScheduledThreadPool

public ScheduledThreadPoolExecutor(int corePoolSize) {
    super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
          new DelayedWorkQueue());
}
  • 线程池特点
    输入核心线程数目
    最大线程数目是Integer.MAXVALUE
    阻塞队列DelayedWorkQueue
    keepAliveTime为0
    可以指定多久以后开始运行第一个线程
    可以指定各个线程按照某种周期速率执行
    用DelayQueue工作队列(是一个任务定时周期执行的队列)
    适用于周期性执行场景

实例代码

/**
    创建一个给定初始延迟的间隔性的任务,之后的下次执行时间是上一次任务从执行到结束所需要的时间+* 给定的间隔时间
    */
    ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);
        scheduledExecutorService.scheduleWithFixedDelay(()->{
            System.out.println("current Time" + System.currentTimeMillis());
            System.out.println(Thread.currentThread().getName()+"正在执行");
        }, 1, 3, TimeUnit.SECONDS);

线程池状态

  • RUNNING
    线程池会接受新的任务,并处理阻塞队列中任务

  • SHUTDOWN
    线程池不会接受新的任务,但是会处理阻塞队列中任务

  • STOP
    线程池不会接受新的任务,也不会处理阻塞中任务,而且中断正在进行的任务

  • TIDYING
    所有任务已经运行终止,任务数量的为0

  • TERMINATED
    该线程池完全终止

  • 线程池各个状态切换

参考

juejin.cn/post/684490…