问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

JUC并发编程——线程池介绍及底层实现

发布网友 发布时间:2024-09-17 01:50

我来回答

1个回答

热心网友 时间:2024-10-01 03:09

1、线程池介绍

池化技术

池化技术是一种很常见的编程技巧,在请求量大时能明显优化应用性能,降低系统频繁建连的资源开销。我们日常工作中常见的有数据库连接池、线程池、对象池等,它们的特点都是将“昂贵的”、“费时的”的资源维护在一个特定的“池子”中,规定其最小连接数、最大连接数、阻塞队列等配置,方便进行统一管理和复用,通常还会附带一些探活机制、强制回收、监控一类的配套功能。

线程池

在真实的生产环境中,可能需要很多线程来支撑整个应用,当线程数量非常多时,反而会耗尽CPU资源。如果不对线程进行控制与管理,反而会影响程序的性能。

线程开销主要包括:创建与启动线程的开销;线程销毁开销;线程调度的开销;线程数量受限CPU处理器数量。

线程池就是有效使用线程的一种常用方式。

线程池内部可以预先创建一定数量的工作线程,客户端代码直接将任务作为一个对象提交给线程池,线程池将这些任务缓存在工作队列中,线程池中的工作线程不断地从队列中取出任务并执行。

线程池的好处:

减低资源消耗

提高响应速度

方便管理

2、线程池的简单使用

JDK提供了一套Executor工具类,可以帮助开发人员有效的使用线程池。

线程池的创建和使用

publicclassThreadPool{publicstaticvoidmain(String[]args){ExecutorServicethreadExecutor=Executors.newFixedThreadPool(3);//创建3个线程大小的线程池try{//向线程池中提交5个任务,这18个任务存储到线程池的阻塞队列中,线程池中这3个线程就从阻塞队列中取任务执行for(inti=0;i<5;i++){//使用线程池后,用线程池创建线程threadExecutor.execute(()->{System.out.println(Thread.currentThread().getName()+"ok");});}}catch(Exceptione){e.printStackTrace();}finally{//使用完后关闭线程池threadExecutor.shutdown();}}}3、线程池底层实现3.1、三大方法源码分析

查看Executors工具类中newCachedThreadPool(),newSingleThreadExcecutor(),newFixedThreadPool()源码:

newCachedThreadPool():创建一个大小可伸缩的线程池

publicstaticExecutorServicenewCachedThreadPool(){returnnewThreadPoolExecutor(0,Integer.MAX_VALUE,60L,TimeUnit.SECONDS,newSynchronousQueue<Runnable>());

newSingleThreadExcecutor():创建单个线程大小的线程池

publicstaticExecutorServicenewSingleThreadExecutor(){returnnewFinalizableDelegatedExecutorService(newThreadPoolExecutor(1,1,0L,TimeUnit.MILLISECONDS,newLinkedBlockingQueue<Runnable>()));

newFixedThreadPool():创建一个固定大小的线程池

publicstaticExecutorServicenewFixedThreadPool(intnThreads){returnnewThreadPoolExecutor(nThreads,nThreads,0L,TimeUnit.MILLISECONDS,newLinkedBlockingQueue<Runnable>());3.2、七大参数

Excutors工具类中返回线程池的方法底层都使用了ThreadPoolExecutor线程池,这些方法都是ThreadPoolExecutor线程池的封装:

publicThreadPoolExecutor(intcorePoolSize,intmaximumPoolSize,longkeepAliveTime,TimeUnitunit,BlockingQueue<Runnable>workQueue,ThreadFactorythreadFactory,RejectedExecutionHandlerhandler)

各个参数含义:

corePoolSize,指定线程池中核心线程的数量。

maxinumPoolSize,指定线程池中最大线程数量。

keepAliveTime,当线程池线程的数量超过corePoolSize时,多余的空闲线程的存活时长,即空闲线程在多长时长内销毁。

unit,是keepAliveTime时长单位。

workQueue,任务队列,把任务提交到该任务队列中等待执行。

threadFactory,线程工厂,用于创建线程。

handler拒绝策略,当任务太多来不及处理时,如何拒绝。

3.3、四大拒绝策略

ThreadPoolExecutor构造方法的最后一个参数指定了拒绝策略.当提交给线程池的任务量超过实际承载能力时,如何处理?即线程池中的线程已经用完了,等待队列也满了,无法为新提交的任务服务,可以通过拒绝策略来处理这个问题.JDK提供了四种拒绝策略:

●AbortPolicy策略,会抛出异常(默认使用)。

●CallerRunsPolicy策略,只要线程池没关闭,会在调用者线程中运行当前被丢弃的任务。

●DiscardOldestPolicy将任务队列中最老的任务丢弃,尝试再次提交新任务。

●DiscardPolicy直接丢弃这个无法处理的任务。

参考文章:http://www.bjpowernode.com/javathread/1233.html

4、自定义创建线程池

在阿里巴巴Java开发手册中说明,创建线程池最好用ThreadPoolExecutor,可以避免OOM(内存溢出):

创建线程池代码说明:

ExecutorServicethreadExecutor=newThreadPoolExecutor(2,//指定线程池中核心线程的数量5,//指定线程池中最大线程数量3,//空闲线程在多长时长内销毁TimeUnit.SECONDS,//单位snewLinkedBlockingQueue<>(10),//基于链表实现的可选容量的阻塞队列,把任务提交到该任务队列中等待执行Executors.defaultThreadFactory(),//默认的线程池工厂newThreadPoolExecutor.CallerRunsPolicy());//拒绝策略:将任务队列中最老的任务丢弃,尝试再次提交新任务

补充:如何设置线程池中最大线程数量

1、CPU密集型:最大线程数量参考值应等于CPU核数+1

//获取CPU核数Runtime.getRuntime().availableProcessors()

cpu使用率较高(也就是一些复杂运算,逻辑处理)

2、I/O密集型:最大线程数量参考值应等于CPU核数x2

CPU消耗很少,任务的大部分时间都在等待IO操作完成(因为IO的速度远远低于CPU和内存的速度)

热心网友 时间:2024-10-01 03:12

1、线程池介绍

池化技术

池化技术是一种很常见的编程技巧,在请求量大时能明显优化应用性能,降低系统频繁建连的资源开销。我们日常工作中常见的有数据库连接池、线程池、对象池等,它们的特点都是将“昂贵的”、“费时的”的资源维护在一个特定的“池子”中,规定其最小连接数、最大连接数、阻塞队列等配置,方便进行统一管理和复用,通常还会附带一些探活机制、强制回收、监控一类的配套功能。

线程池

在真实的生产环境中,可能需要很多线程来支撑整个应用,当线程数量非常多时,反而会耗尽CPU资源。如果不对线程进行控制与管理,反而会影响程序的性能。

线程开销主要包括:创建与启动线程的开销;线程销毁开销;线程调度的开销;线程数量受限CPU处理器数量。

线程池就是有效使用线程的一种常用方式。

线程池内部可以预先创建一定数量的工作线程,客户端代码直接将任务作为一个对象提交给线程池,线程池将这些任务缓存在工作队列中,线程池中的工作线程不断地从队列中取出任务并执行。

线程池的好处:

减低资源消耗

提高响应速度

方便管理

2、线程池的简单使用

JDK提供了一套Executor工具类,可以帮助开发人员有效的使用线程池。

线程池的创建和使用

publicclassThreadPool{publicstaticvoidmain(String[]args){ExecutorServicethreadExecutor=Executors.newFixedThreadPool(3);//创建3个线程大小的线程池try{//向线程池中提交5个任务,这18个任务存储到线程池的阻塞队列中,线程池中这3个线程就从阻塞队列中取任务执行for(inti=0;i<5;i++){//使用线程池后,用线程池创建线程threadExecutor.execute(()->{System.out.println(Thread.currentThread().getName()+"ok");});}}catch(Exceptione){e.printStackTrace();}finally{//使用完后关闭线程池threadExecutor.shutdown();}}}3、线程池底层实现3.1、三大方法源码分析

查看Executors工具类中newCachedThreadPool(),newSingleThreadExcecutor(),newFixedThreadPool()源码:

newCachedThreadPool():创建一个大小可伸缩的线程池

publicstaticExecutorServicenewCachedThreadPool(){returnnewThreadPoolExecutor(0,Integer.MAX_VALUE,60L,TimeUnit.SECONDS,newSynchronousQueue<Runnable>());

newSingleThreadExcecutor():创建单个线程大小的线程池

publicstaticExecutorServicenewSingleThreadExecutor(){returnnewFinalizableDelegatedExecutorService(newThreadPoolExecutor(1,1,0L,TimeUnit.MILLISECONDS,newLinkedBlockingQueue<Runnable>()));

newFixedThreadPool():创建一个固定大小的线程池

publicstaticExecutorServicenewFixedThreadPool(intnThreads){returnnewThreadPoolExecutor(nThreads,nThreads,0L,TimeUnit.MILLISECONDS,newLinkedBlockingQueue<Runnable>());3.2、七大参数

Excutors工具类中返回线程池的方法底层都使用了ThreadPoolExecutor线程池,这些方法都是ThreadPoolExecutor线程池的封装:

publicThreadPoolExecutor(intcorePoolSize,intmaximumPoolSize,longkeepAliveTime,TimeUnitunit,BlockingQueue<Runnable>workQueue,ThreadFactorythreadFactory,RejectedExecutionHandlerhandler)

各个参数含义:

corePoolSize,指定线程池中核心线程的数量。

maxinumPoolSize,指定线程池中最大线程数量。

keepAliveTime,当线程池线程的数量超过corePoolSize时,多余的空闲线程的存活时长,即空闲线程在多长时长内销毁。

unit,是keepAliveTime时长单位。

workQueue,任务队列,把任务提交到该任务队列中等待执行。

threadFactory,线程工厂,用于创建线程。

handler拒绝策略,当任务太多来不及处理时,如何拒绝。

3.3、四大拒绝策略

ThreadPoolExecutor构造方法的最后一个参数指定了拒绝策略.当提交给线程池的任务量超过实际承载能力时,如何处理?即线程池中的线程已经用完了,等待队列也满了,无法为新提交的任务服务,可以通过拒绝策略来处理这个问题.JDK提供了四种拒绝策略:

●AbortPolicy策略,会抛出异常(默认使用)。

●CallerRunsPolicy策略,只要线程池没关闭,会在调用者线程中运行当前被丢弃的任务。

●DiscardOldestPolicy将任务队列中最老的任务丢弃,尝试再次提交新任务。

●DiscardPolicy直接丢弃这个无法处理的任务。

参考文章:http://www.bjpowernode.com/javathread/1233.html

4、自定义创建线程池

在阿里巴巴Java开发手册中说明,创建线程池最好用ThreadPoolExecutor,可以避免OOM(内存溢出):

创建线程池代码说明:

ExecutorServicethreadExecutor=newThreadPoolExecutor(2,//指定线程池中核心线程的数量5,//指定线程池中最大线程数量3,//空闲线程在多长时长内销毁TimeUnit.SECONDS,//单位snewLinkedBlockingQueue<>(10),//基于链表实现的可选容量的阻塞队列,把任务提交到该任务队列中等待执行Executors.defaultThreadFactory(),//默认的线程池工厂newThreadPoolExecutor.CallerRunsPolicy());//拒绝策略:将任务队列中最老的任务丢弃,尝试再次提交新任务

补充:如何设置线程池中最大线程数量

1、CPU密集型:最大线程数量参考值应等于CPU核数+1

//获取CPU核数Runtime.getRuntime().availableProcessors()

cpu使用率较高(也就是一些复杂运算,逻辑处理)

2、I/O密集型:最大线程数量参考值应等于CPU核数x2

CPU消耗很少,任务的大部分时间都在等待IO操作完成(因为IO的速度远远低于CPU和内存的速度)

声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
刘德华《忘情水》歌词 忘情水专辑 忘情水 求 忘情水-刘德华 无损音质 华东理工大学长江学院怎么样 东华理工大学长江学院机械工程系考研情况 南昌教育学院跟东华理工大学的长江学院比哪个好? 东华理工大学和东华理工大学长江学院是同一所吗 东华理工大学长江学院考研难吗 CKC证书是啥意思? ckc康复是什么意思? Python 线程池 (thread pool) 创建及使用 + 实例代码 四十岁的人还没结婚是不是很奇怪? 线程池的7种创建方式 你们觉得不谈恋爱不结婚的人奇怪吗? 线程池中的线程是怎么创建的?是一开始就随着线程池的启动创建好的... 梦见表哥赢了万 新手设计师必备!23 个 实用设计工具推荐 | Eagle 轻松取代 AE!14 个免费动态图像设计软件及工具 | Eagle 适用于Windows的5个最佳Procreate替代品 电脑技巧:认识全能绘画软件Krita(附下载)​ 怎么取消浏览器的账号? 海虾是什么意思 海虾功用主治-海虾的功效 海虾的食用价值怎么样? 海虾能生吃吗 米加仓念什么 肠镜息肉严重吗 做肠镜有息肉严重吗 黄冈的车牌号是什么开头? 玫瑰痤疮的类型有哪些? 今天认识一个男人45岁了竟然还没结婚,是不是很奇怪很可怕? 成语什么末节 以“节”字结尾的成语 形容母亲坚强的句子为母则刚精选116句 麸皮 麦子 玉米面怎样做钓鱼窝料? 麸皮打窝钓草鱼可以吗 人一般有几个兴趣爱好最好? 一个人有多少爱好正常,女朋友问我 除了听音乐唱歌,骑行,没有别的爱... 男人爱好很多好吗? 13800元的复古水冷街车,标配ABS、20升油箱,还有滑动离合 艺术绘画中的象征意义 校服会阻止我们展示自己的个性吗? 请用英语回答 谢谢 急!! ac适配器是什么意思 - 知百科 长江后浪推前浪——Yoga 16s评测 陌生人要你的手机后四位数和你的真名会被骗吗提供手机号码后四位... 孩子考试取得好成绩怎么奖励? 甘肃2024年有什么中专学校 河北考生多少分能上湖北孝感美珈职业学院 国外牛奶做酸奶很稀 湖北孝感美珈职业学院正规吗