六、Java线程池
2021/10/9 14:48:55
本文主要是介绍六、Java线程池,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
文章目录
- 6.1为什么用线程池?
- 6.2线程池如何使用
- 6.2.1线程池的架构说明
- 6.2.2创建线程池3种
- 6.2.3ThreadPoolExecutor底层原理
- 6.3线程池7个重要的参数
- 6.4线程池底层工作原理
- 6.5线程池用哪个?生产中如何设置合理参数?
- 6.5.1线程池的拒绝策略
- 6.5.2三种创建线程池的方法那个用的多?都不用
- 6.5.3自定义线程池
6.1为什么用线程池?
6.2线程池如何使用
![image-20211007124010272](/upload/202110/09/202110091448525898.png)
线程池的工具类:
- Arrays:数组的工具类
- Collections:集合的工具类
- Executors:线程池的工具类
6.2.1线程池的架构说明
Java中的线程池是通过Executor框架实现的,该框架中用到了Executor、Executors、 ExecutorService、 ThreadPoolExecutor这几个类
![image-20211007132729985](/upload/202110/09/202110091448527460.png)
6.2.2创建线程池3种
-
Executors.newFixedThreadPool(int) 创建指定线程数量的线程池
-
Executors.newSingleThreadExecutor() 创建只有一个线程的线程池
-
Executors.newCachedThreadPool() 根据需要创建新的线程,可扩容
Executors.newFixedThreadPool(int)
public class MyThreadDemo { public static void main(String[] args) { ExecutorService threadPool = Executors.newFixedThreadPool(5); //一池5个工作线程,类似一个银行有5个受理窗口 try { //模拟有10个顾客过来银行办理业务,目前池子里面有5个工作人员提供服务 for (int i = 1; i < 10; i++) { threadPool.execute(()->{ System.out.println(Thread.currentThread().getName()+" 办理业务"); }); } }catch (Exception e){ e.printStackTrace(); }finally { threadPool.shutdown(); } } } pool-1-thread-1 办理业务 pool-1-thread-1 办理业务 pool-1-thread-4 办理业务 pool-1-thread-2 办理业务 pool-1-thread-2 办理业务 pool-1-thread-5 办理业务 pool-1-thread-3 办理业务 pool-1-thread-4 办理业务 pool-1-thread-1 办理业务
注意:线程池的名字自己有
Executors.newSingleThreadExecutor()
public class MyThreadDemo { public static void main(String[] args) { ExecutorService threadPool = Executors.newSingleThreadExecutor(); //y一池1个工作线程,类似一个银行有1个受理窗口 try { //模拟有10个顾客过来银行办理业务,目前池子里面有1个工作人员提供服务 for (int i = 1; i < 10; i++) { threadPool.execute(()->{ System.out.println(Thread.currentThread().getName()+" 办理业务"); }); } }catch (Exception e){ e.printStackTrace(); }finally { threadPool.shutdown(); } } } pool-1-thread-1 办理业务 pool-1-thread-1 办理业务 pool-1-thread-1 办理业务 pool-1-thread-1 办理业务 pool-1-thread-1 办理业务 pool-1-thread-1 办理业务 pool-1-thread-1 办理业务 pool-1-thread-1 办理业务 pool-1-thread-1 办理业务
Executors.newFixedThreadPool(int) 问题:假设创建了拥有5个线程的线程池,如果只有2个线程来访问则浪费
Executors.newSingleThreadExecutor() 问题:假设创建了拥有1个线程的线程池,如果有多个线程来访问则造成浪费
Executors.newCachedThreadPool()
可以解决上述问题,动态创建
Executors.newCachedThreadPool()
public class MyThreadDemo { public static void main(String[] args) { ExecutorService threadPool = Executors.newCachedThreadPool(); //一池N个工作线程,类似一个银行有N个受理窗口 try { //模拟有10个顾客过来银行办理业务,目前池子里面有N个工作人员提供服务 for (int i = 1; i < 10; i++) { threadPool.execute(()->{ System.out.println(Thread.currentThread().getName()+" 办理业务"); }); } }catch (Exception e){ e.printStackTrace(); }finally { threadPool.shutdown(); } } } pool-1-thread-2 办理业务 pool-1-thread-1 办理业务 pool-1-thread-3 办理业务 pool-1-thread-4 办理业务 pool-1-thread-5 办理业务 pool-1-thread-1 办理业务 pool-1-thread-3 办理业务 pool-1-thread-2 办理业务 pool-1-thread-4 办理业务
6.2.3ThreadPoolExecutor底层原理
6.3线程池7个重要的参数
![image-20211007141208453](/upload/202110/09/202110091448532353.png)
- corePoolSize:线程池中的常驻核心线程数,线程池中会维护一个最小的线程数量,即使这些线程处于空闲状态,他们也不会被销毁,除非设置了allowCoreThreadTimeOut
- maximumPoolSize:线程池中能够容纳同时执行的最大线程数,此值必须大于等于1
- CPU 密集型程序:maximumPoolSize设置成核心数
Runtime.getRuntime().availableProcessors()获取核心数
- I/O 密集型程序:maximumPoolSize设置成CPU核心数的两倍最佳
- keepAliveTime:多余的空闲线程的存活时间,当前池中线程数量超过corePoolSize时,当空闲时间达到keepAliveTime时,多余线程会被销毁直到只剩下corePoolSize个线程为止
- unit :空闲线程存活时间单位 keepAliveTime的计量单位
- workQueue :任务队列,被提交但尚未被执行的任务
- threadFactory :线程工厂创建一个新线程时使用的工厂,可以用来设定线程名、是否为daemon线程等
- handler :拒绝策略,表示当队列满了,并且工作线程大于等于线程池的最大线程数(maximumPoolSize)时如何来拒绝请求执行的runnable的策略
解释:
假设一个银行网点常驻办理窗口3个(corePoolSize),如果突然很多顾客来办理业务,将无法及时办理业务的顾客让其在等候区排队(workQueue),如果等候区也满了,将窗口增加至5个(maximumPoolSize)。如果5个窗口满了而且等候区也满了,则关门拒绝提供服务(handler)。假如一段时间内(keepAliveTime)都只有少于3个顾客,此时3个窗口已经够用,将5个窗口减少至3个,也就是空闲线程失活。
6.4线程池底层工作原理
6.5线程池用哪个?生产中如何设置合理参数?
6.5.1线程池的拒绝策略
是什么?
等待队列已经排满了
,再也塞不下新任务了,同时线程池中的max线程也达到了
,无法继续为新任务服务,这是就需要拒绝策略机制合理的处理这个问题。
JDK内置的拒绝策略
-
AbortPolicy(默认):直接抛出RejectedExecutionException异常阻止系统正常运行
-
CallerRunsPolicy:调用者运行,一种调节机制,该策略既不会抛弃任务,也不会抛出异常,而是将某些任务回退到调用者,从而降低新任务的流量。
-
DiscardPolicy:该策略默默地丢弃无法处理的任务,不予任何处理也不抛出异常,如果允许任务的丢失,这是最好的一种策略。
-
DiscardOldestPolicy:抛弃队列中等待最久的任务,然后把当前任务加入队列中,尝试再次提交当前任务
6.5.2三种创建线程池的方法那个用的多?都不用
阿里巴巴开发手册
6.5.3自定义线程池
当使用AbortPolicy拒绝策略时
,如果线程数量超过maximumPoolSize+workQueue则报错
public class MyThreadDemo { public static void main(String[] args) { ThreadPoolExecutor threadPool= new ThreadPoolExecutor(2,5,2L, TimeUnit.SECONDS, new LinkedBlockingQueue<>(3),Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy()); try { for (int i = 0; i < 9; i++) { threadPool.execute(()->{ System.out.println(Thread.currentThread().getName()+" 办理业务"); }); } }catch (Exception e){ e.printStackTrace(); }finally { threadPool.shutdown(); } } }
当使用CallerRunsPolicy拒绝策略时
,如果线程数量超过maximumPoolSize+workQueue则回退给调用者运行
public class MyThreadDemo { public static void main(String[] args) { ThreadPoolExecutor threadPool= new ThreadPoolExecutor(2,5,2L, TimeUnit.SECONDS, new LinkedBlockingQueue<>(3),Executors.defaultThreadFactory(),new ThreadPoolExecutor.CallerRunsPolicy()); ..... 省略,同上 } }
当使用DiscardPolicy拒绝策略时
,如果线程数量超过maximumPoolSize+workQueue则丢弃无法处理的线程
public class MyThreadDemo { public static void main(String[] args) { ThreadPoolExecutor threadPool= new ThreadPoolExecutor(2,5,2L, TimeUnit.SECONDS, new LinkedBlockingQueue<>(3),Executors.defaultThreadFactory(),new ThreadPoolExecutor.DiscardPolicy()); ..... 省略,同上 } }
只运行了8个任务,有一个任务被抛弃
当使用DiscardOldestPolicy拒绝策略时
,如果线程数量超过maximumPoolSize+workQueue则抛弃队列中等待最久的任务
public class MyThreadDemo { public static void main(String[] args) { ThreadPoolExecutor threadPool= new ThreadPoolExecutor(2,5,2L, TimeUnit.SECONDS, new LinkedBlockingQueue<>(3),Executors.defaultThreadFactory(),new ThreadPoolExecutor.DiscardOldestPolicy()); ..... 省略,同上 } }
这篇关于六、Java线程池的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-06-19《2023版Java工程师》课程升级公告
- 2024-06-15matplotlib作图不显示3D图,怎么办?
- 2024-06-1503-Loki 日志监控
- 2024-06-1504-让LLM理解知识 -Prompt
- 2024-06-05做软件测试需要懂代码吗?
- 2024-06-0514-ShardingSphere的分布式主键实现
- 2024-06-03为什么以及如何要进行架构设计权衡?
- 2024-05-31全网首发第二弹!软考2024年5月《软件设计师》真题+解析+答案!(11-20题)
- 2024-05-31全网首发!软考2024年5月《软件设计师》真题+解析+答案!(21-30题)
- 2024-05-30【Java】百万数据excel导出功能如何实现