线程池
不需要频繁创建和销毁
为什么使用线程池?
并发量大的情况下频繁的创建销毁线程开销大
创建线程池来缓解压力
构造器中各个参数的含义(7个)
corePoolSize:核心线程池数量,在创建后,核心线程池数量默认为0,有任务来了后才会去创建线程去执行,或者调用prestartAllCoreThreads或者prestartCoreThread()方法进行预创建
maximumPoolSize:线程池总数量,表示在线程中最多能装多少个线程
unit:为keepAliveTime定义时间单位
keepAliveTime:值得是非核心线程池中的线程在没有任务执行时空闲多长时间后被销毁
workQueue:等待队列,可以自己来指定等待队列的实现类
threadFactory:,线程工厂主要用来创建线程
handler:表示处理拒绝任务时的拒绝策略
线程池的执行
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lRodbdDF-1642513624398)(C:\Users\云\AppData\Roaming\Typora\typora-user-images\1642488542146.png)]
当有任务提交过来时,首先检测核心线程池是否已满,未满:在核心线程池创建一个线程处理,已满:将任务添加到等待对列中
继续有任务提交过来,核心线程池已满,等待对列已满,这时就要创建非核心线程来处理任务
如果任务继续增多,核心线程池,等待对列,非核心线程池都已满,那么使用相应的拒绝策略处理
线程池的拒绝策略
AbortPolicy 策略:抛出异常
iscardOleddestPolicy策略:该策略将丢弃最老的一个请求
DiscardPolicy 策略:该策略丢弃无法处理的任务,不予任何处理。
CallerRunsPolicy:让提交任务的线程去执行,例如我们的main线程
execute与submit的区别
execute与submit都是向线程池提交任务的,它们的主要区别是:
execute 没有返回值
submit 可以接收返回值
线程池关闭
关闭线程池可以调用shutdownNow和shutdown两个方法来实现.
shutdownNow:对正在执行的任务全部发出 interrupt(),停止执行,对还未开始执行的任务全部取消,并且返回还没开始的任务列表。 即立即终止线程任务。
shutdown:当我们调用 shutdown 后,线程池将不再接受新的任务,但也不会去强制终止已经提交或者正在执行中的任务。 即不接受新的任务,执行完任务关闭。
创建线程的方法:
1.继承Thread类 2.实现Runnable接口 3.实现Callable接口 4. 使用线程池
ThreadLocal
ThreadLocal 叫做线程变量。
意思是 ThreadLocal 中填充的变量属于当前线程,该变量对其他线程而言是隔离的。ThreadLocal
为每一个线程保存一个变量副本,使得多个线程间变量相互不影响。
ThreadLocal 原理分析
创建一个ThreadLocal对象
调用set方法,会在底层获取到当前正在执行的线程对象,为我们的当前线程创建一个ThreadLocalMap对象
ThreadLocalMap的键是ThreadLocal对象,值就是我们自己set的值
找的时候,先通过我们自己线程去找对象的ThreadLocalMap
Thread t = Thread.currentThread();
ThreadLocalMap map= getMap(t);
ThreadLocal 内存泄漏问题
内存泄露:就是有些对象在内存中已经不被使用,但是不能被回收掉。
ThreadLocalMap 的键是ThreadLocal,是一个被弱引用的对象管理的,如果长时间的线程执行,那么键是弱引用,键就被回收了,为null,但是value可能还一直被占用着,是强引用,不能被回收掉,早成内存泄露。
解决方法:在ThreadLocal中的变量被使用完成后立即将其删除。