线程池

搭配先学我的博客中另一篇 多线程超基本知识 更佳噢~

一、创建

1、Executors


2、new ThreadPoolExecutor【原生线程池,alibaba规范推荐】

七大参数

// JDK8 英文解释
/**
 * Creates a new {@code ThreadPoolExecutor} with the given initial
 * parameters.
 *
 * @param corePoolSize the number of threads to keep in the pool, even
 *        if they are idle, unless {@code allowCoreThreadTimeOut} is set
 * @param maximumPoolSize the maximum number of threads to allow in the
 *        pool
 * @param keepAliveTime when the number of threads is greater than
 *        the core, this is the maximum time that excess idle threads
 *        will wait for new tasks before terminating.
 * @param unit the time unit for the {@code keepAliveTime} argument
 * @param workQueue the queue to use for holding tasks before they are
 *        executed.  This queue will hold only the {@code Runnable}
 *        tasks submitted by the {@code execute} method.
 * @param threadFactory the factory to use when the executor
 *        creates a new thread
 * @param handler the handler to use when execution is blocked
 *        because the thread bounds and queue capacities are reached
 * @throws IllegalArgumentException if one of the following holds:<br>
 *         {@code corePoolSize < 0}<br>
 *         {@code keepAliveTime < 0}<br>
 *         {@code maximumPoolSize <= 0}<br>
 *         {@code maximumPoolSize < corePoolSize}
 * @throws NullPointerException if {@code workQueue}
 *         or {@code threadFactory} or {@code handler} is null
 */
public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue,
                          ThreadFactory threadFactory,
                          RejectedExecutionHandler handler) {}

corePoolSize:核心线程数【只要线程池不销毁就一直存在,除非设置了 allowCoreThreadTimeOut 核心线程超时属性】;线程池创建好以后就准备就绪的线程数量,就等待来接受异步任务去执行。

比如设置为 5,就相当于 new 了 5 个 Thread,等到给线程池提交任务 execute(new Runnable()) 后 才会 start。


maximumPoolSize:最大线程数量;控制资源并发。

比如设置为200,就算此时提交了 100w 个异步任务,当前也只有 200 个线程正在运行,不会导致资源过大而耗尽资源。

keepAliveTime:存活时间;如果当前的线程数量大于 corePoolSize 核心线程数量(是一直存在的,即使空闲了也不会被释放),就会释放空闲的线程。

只要线程空闲时间大于指定的 keepAliveTime 存活时间,就会释放空闲的线程(maximumPoolSize - corePoolSize)。


unit:时间单位;可以用于指定存活时间的时间单位。


BlockingQueue workQueue:阻塞队列;如果提交的任务有很多,就会把目前多出的任务放在队列里面,只要有线程空闲了,就会去队列中取出新的任务继续执行。

比如前面我们设置了 maximumPoolSize 最大线程数量为 200,此时有 1000 个任务被提交过来了,就多出了 800,那这 800 就会被存放在 workQueue 阻塞队列中,等有线程空闲了,再被线程分配。


threadFactory:线程的创建工厂;是如何 new Thread 的,工厂是默认的,当然也可以自定义,比如每次创建线程的时候对线程名字可以有自己的约束,就可以自己写一个线程创建工厂。


RejectedExecutionHandler handler:如果 workQueue 阻塞队列满了,按照我们指定的拒绝策略 RejectedExecutionHandler 拒绝执行任务。

  • DiscardOldestPolicy:丢弃任务阻塞队列中最老的任务,队列中队头的任务

  • CallerRunsPolicy:直接调用 run 方法,异步任务进来本来要启动任务执行,但是内存不够了,资源控制,最大线程满了,队列也满了,就直接调用进来的 run 方法,也不启动进来的线程了,做了一个同步调用

  • AbortPolicy:丢弃新来的任务,新来的任务就直接不要了,这个丢弃会抛异常

  • DiscardPolicy:丢弃新来的任务,丢弃当前的任务,与 AbortPolicy 不同的是丢弃不抛异常

ThreadPoolExecutor executor = new ThreadPoolExecutor(5,
        200,
        10,
        TimeUnit.SECONDS,
        new LinkedBlockingDeque<>(100000),	// 默认是 Integer 的最大值,有可能导致内存不够,因此需要指定大小
        Executors.defaultThreadFactory(),
        new ThreadPoolExecutor.AbortPolicy());

工作顺序&运行流程:

  1. 线程池创建,准备好 core 数量的核心线程,准备接受任务
  2. 新的任务进来,用 core 准备好的空闲线程执行
    1. core 满了,就将再进来的任务放入阻塞队列中。空闲的 core 就会自己去阻塞队列获取任务执行
    2. 阻塞队列满了,就直接开新线程执行,最大只能开到 max 指定的数量
    3. max 满了,如果还有新任务进来,就用 RejectedExecutionHandler 拒绝策略拒绝任务
    4. max 都执行完成,有很多空闲,在指定的 keepAliveTime 时间以后,释放 max - core 这些线程,这些线程会自动销毁,最终保持到 core 大小
  3. 所有的线程创建都是由指定的 factory 创建的

Q:一个线程池,core :7,max:20,queue:50,100 并发进来怎么分配?

7 个会立即得到执行,50 个会进入队列,再开 13 个进行执行。剩下的 30 个就使用拒绝策略。

如果不要抛弃,还要执行的话,就使用 CallerRunsPolicy 策略同步调用 run 方法

3、常见的 4 种线程池

  • Executors.newCachedThreadPool() core 是 0,所有都可回收
    • 创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程
  • Executors.newFixedThreadPool() 固定大小,core = max,都不可回收
    • 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待
  • Executors.newScheduledThreadPool() 定时任务的线程池,可以定时任务多久后执行
    • 创建一个定长线程池,支持定时及周期性任务执行
  • Executors.newSingleThreadExecutor() 单线程的线程池,后台从队列里面获取任务,挨个执行
    • 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务

4、为什么使用线程池

  • 降低资源的消耗
    • 通过重复利用已经创建好的线程降低线程的创建和销毁带来的损耗
  • 提高响应速度
    • 因为线程池中的线程数没有超过线程池的最大上限时,有的线程处于等待分配任务的状态,当任务来时无需创建新的线程就能执行
  • 提高线程的客观理性
    • 线程池会根据当前系统特点对池内的线程进行优化处理,减少创建和销毁线程带来的系统开销。无限的创建和销毁线程不仅消耗系统资源,还降低系统的稳定性,使用线程池进行统一分配
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值