栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

浅析Java中的线程池

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

浅析Java中的线程池

Java中的线程池

几乎所有需要异步或并发执行任务的程序都可以使用线程池,开发过程中合理使用线程池能够带来以下三个好处:

降低资源消耗提高响应速度提高线程的可管理性 1. 线程池的实现原理

当我们提交一个新任务到线程池时,线程池的处理流程如下:

其中,任何创建新线程的操作都需要获取全局锁。

ThreadPoolExecutor采取上述步骤的设计思路,是为了在执行execute()方法时,尽可能地避免获取全局锁。在ThreadPoolExecutor完成预热后,几乎所有的execute()方法都是执行步骤二,而步骤二不需要获取全局锁。

工作线程在完成当前的任务后,会自己到工作队列中循环获取任务来执行:

2. 线程池的使用 2.1 创建线程池

我们通过ThreadPoolExecutor来创建线程池。

new ThreadPoolExecutor(corePoolSize // 核心线程池大小
                      ,maximumPoolSize // 线程池大小
                      ,keepAliveTime // 最长存活时间
                      ,milliseconds // 时间单位
                      ,runnableTaskQueue // 工作队列
                      ,handler) // 饱和策略

corePoolSize 参数为线程池基本大小,即核心线程池的最大容量。当核心线程池未满时,只要收到新任务都会创建一个新的线程。当核心线程池满且无空闲工作线程时,会将任务存到任务队列中。

**maximumPoolSize **参数为线程池最大数量,即线程池允许创建的最大线程数。如果任务队列满了,将会创建新线程来执行任务,直到线程数量达到该最大数量。值得注意的是如果使用了无界的任务队列,那么这个参数就没有效果。

keepAliveTime 参数为空闲线程存活时间。

**TimeUnit **参数为线程活动保持时间的单位。

**workQueue **参数为任务队列,它是一个用于保存等待执行的任务的阻塞队列,可以选择以下几个。

队列底层是否有界其他
ArrayBlockingQueue数组·有界FIFO
linkedBlockingQueue链表无界FIFO
SynchronousQueue不存储元素有界每个插入操作都必须等到另一个线程调用移除操作
PriorityBlockingQueue数组无界有优先级

ThreadFactor参数为线程工厂。可以通过线程工厂为每个创建出来的线程设置更有意义的名字。

RejectedExecutionHandler参数为饱和策略。当队列和线程池都满了,我们需要使用饱和策略来处理新任务。一般有以下四种策略。

    AbortPolicy:直接抛出异常。CallerRunsPolicy:只用调用者所在线程来运行任务。DiscardOldestPolicy:丢弃队列里最近的一个任务,并执行当前任务。DiscardPolicy:不处理,丢掉。当然,也可以通过RejectedExecutionHandler接口自定义策略,比如记录日志或者持久化存储不能处理的任务。

为什么要求用 ThreadPoolExecutor 创建线程池

否则有资源耗尽的风险,Executors返回的线程池对象弊端如下:

FixedThreadPool和SingleThreadPool:允许的请求队列长度为Integer.MAX_VALUE,可能会堆积大量请求,导致 OOM。CachedThreadPool和ScheduledThreadPool:允许的创建线程数量为Integer.MAx_VALUE,可能会创建大量线程,导致 OOM。 2.2 向线程池提交任务

可以用execute()和submit()两个方法向线程池提交任务,前者提交不需要返回值的任务,后者提交需要返回值的任务。

2.3 关闭线程池

使用shutdown()或shutdownNow()方法来关闭线程池。原理是遍历线程池中的工作线程,逐个调用interrupt()方法。

shutdownNow()会将线程池状态设置为STOP,并尝试停止所有的正在执行或暂停任务的线程,并返回等待执行任务的列表。而shutdown()只是将线程池状态设置为SHUTDOWN状态,然后中断所有没有正在执行任务的线程。

通常调用shutdown()方法,如果任务不一定要执行完,就调用shutdownNow()。

3. 合理配置线程池

我们需要通过任务的特性,来分析合理的线程池配置方式:

任务的性质:CPU 密集型任务、IO 密集型任务和混合型任务

CPU 密集型任务配置尽可能少的线程,如配置 CPU 核数+ 1 个线程。IO 密集型人物应配置尽可能多的线程,如配置 2 * cpu 核数个线程。混合型任务尽量拆分 任务优先级:高、中、低

优先级不同的任务可以使用优先级队列PriorityBlockingQueue来处理。 任务执行时间:长、中、短

执行时间不同的任务交给不同规模的线程池处理。 任务依赖性:是否以来其他系统资源,如数据库资源

依赖数据库连接池的任务,因为线程提交 SQL 后需要等待数据库返回结果,等待时间越长则 CPU 空闲时间越长,那么线程数应该设置得越大,才能更好地使用 CPU。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/716567.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号