【Java】线程池

优势

  1. 降低系统资源消耗:通过重用已存在的线程,降低线程创建和销毁而造成的消耗。
  2. 提高系统响应速度:当有任务到达时可复用已存在的线程,而无需等待新线程的创建便能立即执行。
  3. 方便线程并发数的管控:因为线程若无限制地创建,可能会导致OOM,并且会造成cpu过度切换(cpu切换线程是有时间成本的,需要保存当前执行线程的上下文,并恢复要执行线程的上下文)。
  4. 提供更强大的功能:如定时任务线程池(ScheduledThreadPoolExecutor)。

参数

public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue,
                          ThreadFactory threadFactory,
                          RejectedExecutionHandler handler) {
    if (corePoolSize < 0 ||
        maximumPoolSize <= 0 ||
        maximumPoolSize < corePoolSize ||
        keepAliveTime < 0)
        throw new IllegalArgumentException();
    if (workQueue == null || threadFactory == null || handler == null)
        throw new NullPointerException();
    this.corePoolSize = corePoolSize;
    this.maximumPoolSize = maximumPoolSize;
    this.workQueue = workQueue;
    this.keepAliveTime = unit.toNanos(keepAliveTime);
    this.threadFactory = threadFactory;
    this.handler = handler;
}
  • corePoolSize(核心线程数):当向线程池提交一个任务时,若线程池已创建的线程数小于corePoolSize,即便此时存在空闲线程,也会通过创建一个新线程来执行该任务,直到已创建的线程数 ≥ \ge corePoolSize(除了利用提交新任务来创建和启动线程(按需构造),也可通过prestartCoreThread()或prestartAllCoreThreads()方法来提前启动核心线程)。
  • maximumPoolSize(最大线程数):当队列满了且已创建的线程数小于maximumPoolSize时,线程池会创建新的线程来执行任务(无界队列可忽略该参数)。
  • keepAliveTime(线程存活时间):当线程池中线程数大于corePoolSize时,线程的空闲时间若超过keepAliveTime,那么这个线程就会被销毁,直到线程池中的线程数 ≤ \le corePoolSize。
  • unit(时间单位):即keepAliveTime的时间单位。
  • workQueue(任务队列):即执行前用于保持任务的队列,此队列仅保持由execute方法提交的Runnable任务。
  • threadFactory(线程工厂):用于创建新线程。threadFactory也是采用new Thread()方式来创建线程,且创建的线程名具有统一的风格:pool-m-thread-n(m为线程池的编号,n为线程池内的线程编号)。
  • handler(线程饱和策略):当线程池和队列都满后再加入线程会执行此策略。

实现原理

当提交一个新任务到线程池时,线程池的处理流程如下:

  1. 线程池判断核心线程池里的线程是否都在执行任务:如果不是,则创建一个新的工作线程来执行任务;如果核心线程池里的线程都在执行任务,则进入下个流程。
  2. 线程池判断工作队列是否已经满:如果工作队列没有满,则将新提交的任务存储在这个工作队列里;如果工作队列满了,则进入下个流程。
  3. 线程池判断线程池的线程是否都处于工作状态:如果没有,则创建一个新的工作线程来执行任务;如果已经满了,则交给饱和策略来处理这个任务。

使用场景

在Executors类里面提供了一些静态工厂来生成一些常用的线程池:

  1. newFixedThreadPool:创建固定大小的线程池。线程池的大小一旦达到最大值就会保持不变,如果某个线程因为执行异常而结束,那么线程池会补充一个新线程。
  2. newCachedThreadPool:创建一个可缓存的线程池。如果线程池的大小超过了处理任务所需要的线程,那么会回收部分空闲(60秒不执行任务)的线程,当任务数增加时,此线程池又可以添加新线程来处理任务。此线程池不会对线程池大小做限制,线程池大小完全依赖于操作系统(或者说JVM)能够创建的最大线程大小。
  3. newSingleThreadExecutor:创建一个单线程的线程池。这个线程池只有一个线程在工作,也就是相当于单线程串行执行所有任务。如果这个唯一的线程因为异常结束,那么会有一个新的线程来替代它。此线程池保证所有任务的执行顺序按照任务的提交顺序执行。
  4. newScheduledThreadPool:创建一个大小无限的线程池。此线程池支持定时以及周期性执行任务的需求。
  5. newSingleThreadScheduledExecutor:创建一个单线程的线程池。此线程池支持定时以及周期性执行任务的需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值