ThreadLocal

ThreadLocal

为每一个线程赋值一份变量副本(创建一个ThreadLocal对象,用来为每个线程保存一份变量,实现线程封闭)

底层使用一个ThreadLocalMap对象存储

使用ThreadLocal存在内存泄露问题

​ 使用ThreadLocal对象作为键,是弱引用,可以被回收掉,键为null,但是value值为强引用,不会被回收掉

ThreadLocal正确的使用方法

​ 建议:每次使用完ThreadLocal都调用它的remove()方法清除数据.

线程池

​ 任务多且简单时,为了减少频繁的创建销毁线程的开销

​ 可以使用线程池,预先创建一部分线程,重复使用,减少创建销毁开销

​ jdk5自带创建线程池的类:

ThreadPoolExecutor

​ ThreadPoolExecutor类中的构造器有七个参数:

corePoolSize:核心线程数量(不会被销毁)

​ 1.prestartAllCoreThread() 或者 prestartCoreThread() 方法,预先创建核心数量个线程

​ 2.起初不创建,有任务到达时创建,直到到达核心数量个线程

maximumPoolSize:最大线程数量

keepAliveTime:超出核心数量部分的线程,在没有执行任务的时候,空闲多久后销毁。

unit: keepAliveTime的时间到位,共有六个:

在这里插入图片描述

workQueue:指定等待阻塞队列

threadFactory:线程工厂,主要用来创建线程

handle:表示当拒绝处理任务时的策略

线程池的执行

​ 创建完成ThreadPoolExecutor之后,当向线程池提交任务时,通常使用execute方法。execute方法的执行流程图如下:
在这里插入图片描述

1.如果线程池中存活的核心线程数小于线程数corePoolSize时,线程池会创建一个核心线程去处理提交的任务。

2.如果线程池核心线程数已满,即线程数已经等于corePoolSize,一个新提交的任务,会被放进任务队列workQueue排队等待执行。

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

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

线程池中的队列

线程池有以下工作队列:

ArrayBlockingQueue:有界队列,是一个用数组实现的有界阻塞队列,按FIFO(先入先出)排序量。

LinkedBlockingQueue:可设置容量队列,基于链表结构的阻塞队列,按FIFO排序任务,容量可以选择进行设置,不设置的话,将是一个无边界的阻塞队列,最大长度为Integer.MAX_VALUE,吞吐量通常要高于ArrayBlockingQuene;newFixedThreadPool线程池使用了这个队列。

DelayQueue:延迟队列,是一个任务定时周期的延迟执行的队列。根据指定的执行时间从小到大排序,否则根据插入到队列的先后排序。newScheduledThreadPool线程池使用了这个队列。

PriorityBlockingQueue:优先级队列,是具有优先级的无界阻塞队列。

SynchronousQueue:同步队列,一个不存储元素的阻塞队列,每个插入操作必须等到另一个线程调用移除操作,否则插入操作一直处于阻塞状态,吞吐量通常要高于LinkedBlockingQuene,newCachedThreadPool线程池使用了这个队列。

线程池的拒绝策略

构造方法的中最后的参数RejectedExecutionHandler用于指定线程池的拒绝策略。当请求任务不断的过来,而系统此时又处理不过来的时候,我们就需要采取对应的策略是拒绝服务。

默认有四种类型:

AbortPolicy策略:该策略会直接抛出异常,阻止系统正常工作。

CallerRunsPolicy策略:只要线程池未关闭,该策略直接在调用者线程中,运行当前的被丢弃的任务。

DiscardOleddestPolicy策略:该策略将丢弃最老的一个请求,也就是即将被执行的任务,并尝试再次提交当前任务。

DiscardPolicy策略:该策略默默的丢弃无法处理的任务,不予任何处理。

异常处理

当执行任务时发生异常,那么该怎么处理呢?

​ 首先看当Thread线程异常如何处理。在任务中通过try…catch是可以捕获异常并进行处理的,如下代码:

在这里插入图片描述

execute与submit的区别

执行任务除了可以使用execute方法还可以使用submit方法。它们的主要区别是:

execute适用于不需要关注返回值的场景。

submit方法适用于需要关注返回值的场景。

关闭线程池

关闭线程池可以调用shutdownNow和shutdown两个方法来实现。

shutdownNow:对正在执行的任务全部发出interrupt(),停止执行,对还未开始执行的任务全部取消,并且返回还没开始的任务列表。

shutdown:当我们调用shutdown后,线程池将不再接受新的任务,但也不会去强制终止已经提交或者正在执行中的任务。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值