线程池
线程池
创建多线程的方式 :
Thread 类
Runable接口
Callable Future接口
线程池
为什么需要线程池(了解)
避免线程创建和销毁的消耗,提升响应速度,统一管理
线程池种类
第一类: 缓存共享 newCachedThreadPool
第二类:池子
newFixedThreadPool 固定大小的池子 newScheduledThreadPool 延后多少时间,周期执行的池子
第三类:
newSingleThreadExecutor 单线程 newSingleThreadScheduledExecutor 加延后多少时间,周期执行的池子
执行原理或流程:
1 新任务达到,判断是否达到核心线程线程数,如未达到,新开线程执行任务,如已达到,尝试放到阻塞队列
2 如阻塞队列未满,放到队列中等待执行,如阻塞队列已满,判断最大是否达到最大线程数
3 如未达到,新开线程执行任务,如已达到,安装阻塞策略执行
常用的阻塞策略:
丢弃当前任务并抛异常 直接丢弃当前任务,丢弃最老的任务,不丢弃不抛异常 ,让调用者执行
核心参数
corePoolSize:核心线程池的大小 10 1 方法执行完,先进先出 maximumPoolSize:线程池能创建线程的最大个数 keepAliveTime:空闲线程存活时间 unit:时间单位,为keepAliveTime指定时间单位 workQueue:阻塞队列,用于保存任务的阻塞队列
threadFactory:创建线程的工程类 handler:阻塞策略 关闭: ShutDown
关闭未执行的任务,不关闭正在执行的任务 ShutDownNow 关闭所有正在执行和未执行的任务
为什么需要线程池
在实际使用中,线程是很占用系统资源的,如果对线程管理不完善的话很容易导致系统问题。 因此,在大多数并发框架中都会使用线程池来管理线程,使用线程池管理线程主要有如下好处:
1、使用线程池可以重复利用已有的线程继续执行任务,避免线程在创建销毁时造成的消耗 2、由于没有线程创建和销毁时的消耗,可以提高系统响应速度 3、通过线程可以对线程进行合理的管理,根据系统的承受能力调整可运行线程数量的大小等
线程池的分类
2 newFixedThreadPool:创建一个可重用固定线程数的线程池,以共享的无界队列方式来运行这些线程,线程池中的线程处于一定的量,可以很好的控制线程的并发量
3 newSingleThreadExecutor:创建一个使用单个 worker 线程的Executor ,以无界队列方式来运行该线程。线程池中最多执行一个线程,之后提交的线程将会排在队列中以此执行
4 newSingleThreadScheduledExecutor:创建一个单线程执行程序,它可安排在给定延迟后运行命令或者定期执行
5 newScheduledThreadPool:创建一个线程池,它可安排在给定延迟后运行命令或者定期的执行
6 newWorkStealingPool:创建一个带并行级别的线程池,并行级别决定了同一时刻最多有多少个线程在执行,如不传并行级别参数,将默认为当前系统的CPU个数
核心参数(高薪常问)
corePoolSize:核心线程池的大小 10 1 方法执行完,先进先出 maximumPoolSize:线程池能创建线程的最大个数 keepAliveTime:空闲线程存活时间 unit:时间单位,为keepAliveTime指定时间单位 workQueue:阻塞队列,用于保存任务的阻塞队列
threadFactory:创建线程的工程类 handler:饱和策略(拒绝策略)
线程池的原理
线程池的工作过程如下: 当一个任务提交至线程池之后,
1 线程池首先判断核心线程池里的线程是否已经满了。如果不是,则创建一个新的工作线程来执行任务。否则进入2. 判断工作队列是否已经满了,倘若还没有满,将线程放入工作队列。否则进入3. 3 判断线程池里的线程是否都在执行任务。如果不是,则创建一个新的工作线程来执行。如果线程池满了,则交给饱和策略来处理任务。
拒绝策略(了解)
ThreadPoolExecutor.AbortPolicy(系统默认): 丢弃任务并抛出RejectedExecutionException异常,让你感知到任务被拒绝了,我们可以根据业务逻辑选择重试或者放弃提交等策略 ThreadPoolExecutor.DiscardPolicy: 也是丢弃任务,但是不抛出异常,相对而言存在一定的风险,因为我们提交的时候根本不知道这个任务会被丢弃,可能造成数据丢失。
ThreadPoolExecutor.DiscardOldestPolicy: 丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程),通常是存活时间最长的任务,它也存在一定的数据丢失风险
ThreadPoolExecutor.CallerRunsPolicy:既不抛弃任务也不抛出异常,而是将某些任务回退到调用者,让调用者去执行它。
线程池的关闭(了解)
关闭线程池,可以通过shutdown和shutdownNow两个方法 原理:遍历线程池中的所有线程,然后依次中断
1、shutdownNow首先将线程池的状态设置为STOP,然后尝试停止所有的正在执行和未执行任务的线程,并返回等待执行任务的列表; 2、shutdown只是将线程池的状态设置为SHUTDOWN状态,然后中断所有没有正在执行任务的线程