线程池

什么是线程池?

线程池是一种多线程的处理形式,处理过程中将任务提交到线程池中,任务的执行交由线程池来管理。

如果每个请求都创建一个线程,那么服务器的资源很快就会被消耗完,使用线程池可以减少创建和销毁线程的次数,每个工作线程都可以被重复利用,可执行多个任务。

为什么要使用线程池?

  • 可以帮助我们管理线程,避免增加线程创建和销毁造成资源的消耗

  • 提高响应速度

  • 重复利用

线程池的创建

  • 通过ThreadPoolExecutor()创建

  • 里面的参数

    • corePoolSize:线程池核心线程最大值

    • maxiNumPoolSize:线程池最大线程数

    • keepAliveTime:线程池中非核心线程空闲的存活大小

    • unit:线程空闲存活时间单位

    • workQueue:存放任务的阻塞队列

    • threadFactory:设置创建线程的工厂

    • handler:线程池的饱和策略事件

线程池的任务执行

执行任务用的是execute();

  • 提交一个任务,线程池里存活的线程数小于核心线程数,线程池会创建一个核心线程去执行此次任务

  • 如果核心线程数满了,一个新提交的任务,则会放进任务队列workQueue排队等待执行

  • 当线程池里面存活的线程数已经等于corePoolSize了,并且任务队列workQueue也满,判断线程数是否达到maximumPoolSize,即最大线程数是否已满,如果没到达,创建一个非核心线程执行提交的任务。

  • 如果当前的线程数达到了maximumPoolSize,还有新的任务过来的话,直接采用拒绝策略处理。

四种拒绝策略

  • AbortPolicy(抛出异常)

  • DiscardPolicy(直接丢弃任务)

  • DiscardOldestPolicy(丢弃队列里最老的任务,讲这个任务继续提交到线程池)

  • CallerRunsPolicy(交给线程池调用所在的线程进行处理)

几种常见的线程池及使用场景

  1. newSingleThreadExecutor

    • 创建一个单线程化的线程池,只会用唯一的工作线程执行任务,保证所有的任务都能按照指定的顺序执行

    • 核心线程数为1

    • 最大线程数也为1

    • 阻塞队列是LinkedBlockingQueue

    • keepAliveTime为0

  2. newFixedThreadPool

    1. 创建一个定长线程,控制线程的最大并发数,超出的线程会在队列中等待

    2. 核心线程数和最大线程数大小一样

    3. 没有所谓的非空闲时间,即keepAliveTime为0

    4. 阻塞队列为无界队列LinkedBlockingQueue

      • 提交任务

      • 如果线程数少于核心线程,创建核心线程执行任务

      • 如果线程数等于核心线程,把任务添加到LinkedBlockingQueue阻塞队列

      • 如果线程执行完任务,去阻塞队列取任务,继续执行。

  3. newCachedThreadPool

    1. 创建一个可缓存的线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回,则新建线程

    2. 核心线程数为0

    3. 最大线程数为Integer.MAX_VALUE

    4. 阻塞队列是SynchronousQueue

    5. 非核心线程空闲存活时间为60秒

      • 提交任务

      • 因为没有核心线程,所以任务直接加到SynchronousQueue队列。

      • 判断是否有空闲线程,如果有,就去取出任务执行。

      • 如果没有空闲线程,就新建一个线程执行。

      • 执行完任务的线程,还可以存活60秒,如果在这期间,接到任务,可以继续活下去;否则,被销毁。

  4. newScheduledThreadPool

    1. 创建一个定长线程池,支持定时及周期性执行任务

    2. 最大线程数为Integer.MAX_VALUE

    3. 阻塞队列是DelayedWorkQueue

    4. keepAliveTime为0

    5. scheduleAtFixedRate() :按某种速率周期执行

    6. scheduleWithFixedDelay():在某个延迟后执行

      • 添加一个任务

      • 线程池中的线程从 DelayQueue 中取任务

      • 线程从 DelayQueue 中获取 time 大于等于当前时间的task

      • 执行完后修改这个 task 的 time 为下次被执行的时间

      • 这个 task 放回DelayQueue队列中

execute和submit有啥区别?

  • execute和submit都用来提交所提交的任务

  • execute适用于不用关注返回值的场景,只需要将线程丢到线程池中执行。

  • submit方法适用于关注有返回值的场景

 

线程池有那些工作队列?

  • ArrayBlockingQueue 基于数组的有界阻塞队列

  • LinkedBlockingQueue 基于链表结构的阻塞队列

  • SynchronousQueus 不存储元素的阻塞队列

  • PriorityBlockingQueue 优先级的无限阻塞队列

 

处理线程池异常

  • 在任务代码try /catch 捕捉异常

  • 通过Future对象的get方法接收抛出的异常

  • 为工作者线程设置UncaughtExceptionHandler,在uncaughtException方法中处理异常

  • 重写ThreadPoolExecutor的afterExecute方法,处理传递的异常引用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值