03 Java线程池

为什么要有线程池

1 资源有限

没有用线程池的情况下,需要对每个任务创建一个线程,如果任务较多或线程执行较慢,线程会迅速增加,耗尽内存资源,进而导致服务崩溃。为了更合理的利用资源,需要对线程进行管理,为了避免任务过多而引起的服务异常,需要对任务进行管理

2 线程开销

线程每次创建和销毁时,都会有时间成本,为了提高性能,需要对已创建的线程进行复用。
使用线程池的目的总结来说,就是充分利用系统资源,同时避免过度调度引起的开销。

线程池该怎么用

1 线程池创建

1.1 Executors方式
  1. Executors.newFixedThreadPool:核心线程数一旦指定则固定,核心线程数和最大线程数相等,任务队列队列使用的是未指定容量的链表阻塞队列,链表阻塞队列未指定容量时,默认为Integer最大值。
  2. Executors.newCachedThreadPool:使用SynchronousQueue作为任务队列,新增和删除任务的操作为offer/poll的方式,最大线程数为Integer最大值,对于任意一个任务,每次都会创建一个新的线程来执行它。
  3. Executors.newSingleThreadExecutor:核心线程数和最大线程数都是1,任务队列队列使用的是未指定容量的链表阻塞队列,链表阻塞队列未指定容量时,默认为Integer最大值。
  4. Executors.newSingleThreadExecutor:创建一个定时任务线程池,核心线程数由输入参数指定,最大线程数为Integer.max,任务队列为延时阻塞队列,适用于在未来的某个时间点做某个任务。
  5. Executors.newWorkStealingPool:jdk8引入,内部会构建ForkJoinPool,利用working-stealing算法,并行的处理任务,但是不保证处理顺序。Fork/Join框架,把大任务分解成多个小任务,每个小任务执行完成之后,再合并成最终结果。work-stealing算法:某个线程从其他线程队列里窃取任务来执行。
1.2 ThreadPoolExecutor方式(推荐)

ExecutorService executorService = new ThreadPoolExecutor (corePoolSize,maxPoolSize,keepAliveTime,unit,任务队列,ThreadFactory,RejectedExecutionHandler);
建议使用ExecutorService作为静态类型,可以处理不带返回值的任务(execute)和带返回值的任务(submit),ThreadPoolExecutor接口默认无返回值,

  1. corePoolSize:核心线程数,当前线程数小于核心线程数时,创建新线程(充分利用资源),将当前任务作为线程的第一个任务来执行
  2. 任务队列:当前线程数大于核心线程数,将任务插入到队列,排队等待,线程会不断消费任务队列里的任务,
  3. maxPoolSize:最大线程数,当任务队列满了,且线程数小于最大线程数且小于最大容量(2^29-1),创建新线程
  4. keepAliveTime:如果线程数大于核心线程数,且空闲时长超过keepAliveTime,则销毁线程
  5. ThreadFactory:线程创建工厂,线程池会根据工厂方法来创建线程,通过工厂方法,自定义线程的名称、优先级及其他特性
  6. RejectedExecutionHandler:拒绝策略,当线程池饱和而无法继续执行任务时,采用拒绝策略来处理新任务。
    1. AbortPolicy:拒绝任务并抛出异常
    2. DiscardPolicy:拒绝任务但不抛出异常
    3. DiscardOldestPolicy:丢弃队列中最老的任务,并执行当前任务
    4. CallerRunsPolicy:主线程执行任务

2 执行任务

1 执行流程在这里插入图片描述

2 任务执行

  1. 获取任务:若是核心线程,使用take()方法从队列获取任务,执行完任务后,继续自旋从任务队列获取任务;若是非核心线程,使用poll(keepAliveTime)来获取任务,当执行完第一个任务后,会keepAliveTime超时,返回空任务;
  2. 执行任务:由woker线程调用任务的run方法

3 线程池关闭

  1. shutDown:将线程池状态设为关闭(ShutDown),停止接收新的任务,终止空闲的线程,正在运行的或者等待中的任务将会继续执行
  2. shutDownNow:将线程池状态设为停止,停止接收新的任务,终止(interrupt)所有线程,等待中的任务将不会继续执行,会返回未执行完的任务列表

线程池怎么实现的

1 线程池状态图

在这里插入图片描述

  1. Running:线程池正常运转,接收新的任务
  2. ShutDown:不接收新任务,队列中的任务和正在运行的任务会继续运行
  3. ShutDownNow:不接收新任务,队列中的任务不会运行,中止正在运行中的任务
  4. Tiding:线程池数量为空,队列任务为空时
  5. Terminated:terminated()方法执行完成之后

2 任务管理

使用阻塞队列来管理任务

3 线程管理

线程池数据结构

Java使用HashSet来管理线程(Worker类),那么HashSet如何唯一确定一个Worker呢?
Worker类并没有重写hashcode和equals,使用的是Object中默认的hashcode和equals方法,默认的equals方法是通过==运算符来判断,hashcode则为native方法,跟对象的monitor相关,有兴趣的可以去查看openjdk源码,hashcode方法可以保证对于同一个对象,hashcode方法会返回同一个值。

线程新增/删除

线程池为共享资源,对于它的操作需要保证线程安全,Java使用ReentrantLock锁来保证,任何对线程池的操作,首先要获取到锁。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值