# 线程池

# 创建多线程的方式 :

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、通过线程可以对线程进行合理的管理,根据系统的承受能力调整可运行线程数量的大小等

# 线程池的分类

img

2 newFixedThreadPool:创建一个可重用固定线程数的线程池,以共享的无界队列方式来运行这些线程,线程池中的线程处于一定的量,可以很好的控制线程的并发量

3 newSingleThreadExecutor:创建一个使用单个 worker 线程的Executor ,以无界队列方式来运行该线程。线程池中最多执行一个线程,之后提交的线程将会排在队列中以此执行

4 newSingleThreadScheduledExecutor:创建一个单线程执行程序,它可安排在给定延迟后运行命令或者定期执行

5 newScheduledThreadPool:创建一个线程池,它可安排在给定延迟后运行命令或者定期的执行

6 newWorkStealingPool:创建一个带并行级别的线程池,并行级别决定了同一时刻最多有多少个线程在执行,如不传并行级别参数,将默认为当前系统的CPU个数

# 核心参数(高薪常问)

corePoolSize:核心线程池的大小 10 1 方法执行完,先进先出 maximumPoolSize:线程池能创建线程的最大个数 keepAliveTime:空闲线程存活时间 unit:时间单位,为keepAliveTime指定时间单位 workQueue:阻塞队列,用于保存任务的阻塞队列
threadFactory:创建线程的工程类 handler:饱和策略(拒绝策略)

# 线程池的原理

img

线程池的工作过程如下: 当一个任务提交至线程池之后,

1 线程池首先判断核心线程池里的线程是否已经满了。如果不是,则创建一个新的工作线程来执行任务。否则进入2. 判断工作队列是否已经满了,倘若还没有满,将线程放入工作队列。否则进入3. 3 判断线程池里的线程是否都在执行任务。如果不是,则创建一个新的工作线程来执行。如果线程池满了,则交给饱和策略来处理任务。

# 拒绝策略(了解)

ThreadPoolExecutor.AbortPolicy(系统默认): 丢弃任务并抛出RejectedExecutionException异常,让你感知到任务被拒绝了,我们可以根据业务逻辑选择重试或者放弃提交等策略 ThreadPoolExecutor.DiscardPolicy: 也是丢弃任务,但是不抛出异常,相对而言存在一定的风险,因为我们提交的时候根本不知道这个任务会被丢弃,可能造成数据丢失。

ThreadPoolExecutor.DiscardOldestPolicy: 丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程),通常是存活时间最长的任务,它也存在一定的数据丢失风险

ThreadPoolExecutor.CallerRunsPolicy:既不抛弃任务也不抛出异常,而是将某些任务回退到调用者,让调用者去执行它。

# 线程池的关闭(了解)

关闭线程池,可以通过shutdown和shutdownNow两个方法 原理:遍历线程池中的所有线程,然后依次中断

1、shutdownNow首先将线程池的状态设置为STOP,然后尝试停止所有的正在执行和未执行任务的线程,并返回等待执行任务的列表; 2、shutdown只是将线程池的状态设置为SHUTDOWN状态,然后中断所有没有正在执行任务的线程

上次更新: 2024/4/13