三大方法:

//线程池核心线程数为n, 最大线程数为 n

ExecutorService fixedThreadPool = Executors.newFixedThreadPool(n);

源码: 可以看到核心线程数, 和最大线程数相同, 这种线程池伸缩性,扩展性不好

//线程池核心线程数为1, 最大线程数为 1

ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();

源码: 可以看到核心线程数, 和最大线程数都是1, 实际生产中这种线程池用的很少,基本不会用

//缓存线程池: 无限大小

ExecutorService cachedThreadPool = Executors.newCachedThreadPool();

源码: 核心线程数为0, 最大线程数为Integer.MAX_VALUE = 21亿多, 实际生产中几乎永远不会达到最大线程数, 而且越来越多任务堆积在阻塞队列中,会造成 OOM

实际代码中我们都是使用自定义的线程池: 阿里巴巴开发手册中也是强烈建议,不要用jdk自带的线程池,而要自己定义,这样代码人能够清楚的看到线程池的资源配置

下面是我们自定义的线程池: 7大参数:

        /**
* 线程池 四大拒绝策略: 拒绝策略什么时候生效: 当队列满了,且正在运行的线程数量>=最大maimumPoolSize, 此时拒绝策略生效
* AbortPolicy: 丢弃任务,直接抛异常
* DiscardPolicy 丢弃任务, 不抛异常
* DiscardOldestPolicy: 丢弃队列最前面的任务,然后重新提交被拒绝的任务
* CallerRunsPolicy: 由调用线程(提交任务的线程)处理该任务
**/
ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(
2, //核心线程数
5,//最大线程数
3,// 多余空闲线程存活时间, 当线程池的线程数量超过corePoolSize,, 当空闲线程的空闲时间超过了 这个时间,多余的线程会被销毁,直到只剩下核心线程数量为止
TimeUnit.SECONDS,//空闲时间的单位
new ArrayBlockingQueue<>(3),//阻塞队列,
Executors.defaultThreadFactory(),//默认的线程工厂
//new ThreadPoolExecutor.AbortPolicy());//拒绝策略 : 直接丢弃,抛异常
//new ThreadPoolExecutor.DiscardPolicy());
new ThreadPoolExecutor.DiscardOldestPolicy());
//new ThreadPoolExecutor.CallerRunsPolicy());

文字描述,线程池原理描述: 自定义一个线程池: 核心线程数为2, 最大线程数为5,阻塞队列的大小为3,

1: 当调用execute()方法添加一个请求时候,线程池会做如下判断

*1.1: 如果正在运行的线程数量 小于 corePoolSize,那么马上创建线程执行这个任务

*1.2: 如果正在运行的线程数量 大于/等于 corePoolSize, 那么将这个任务加入阻塞队列

*1.3: 如果这时候 阻塞队列满了,且正在运行的线程数量 小于 maximumPoolSize , 那么就创建 非核心线程 立刻运行这个任务(稍后代码验证,这里是新开一个非核心线程立即执行这个任务 )

*1.4: 如果队列满了, 且正在运行的线程数量 大于/等于 maximumPoolSize , 那么线程池开启拒绝策略来执行

3: 当一个线程完成任务,他会从阻塞队列中取下一个任务来执行

4: 当一个线程无事可做 且超过一定时间(keepAliveTime)时,线程池会判断: 如果当前运行的线程 大于 corePoolSize, 那么这个线程就停掉.

问:

1, 目前自定义的这个线程池, 什么时候开启拒绝策略? 答:当有8个任务, 当队列满,且正在运行的线程等于最大线程数, 最大线程数为5, 队列为3,所以为 8, 当有8个任务时候,此时不抛异常,但是已经开启了拒绝策略,第九个来的时候,就抛异常

2, 如果这时候 阻塞队列满了,且正在运行的线程数量 小于 maximumPoolSize , 那么就创建 非核心线程 立刻运行这个任务 ? 这个怎么证明

3, 四大拒绝策略怎么理解,证明的效果是?

        /**
* 线程池 四大拒绝策略: 拒绝策略什么时候生效: 当队列满了,且正在运行的线程数量>=最大maimumPoolSize, 此时拒绝策略生效
* AbortPolicy: 丢弃任务,直接抛异常
* DiscardPolicy 丢弃任务, 不抛异常
* DiscardOldestPolicy: 丢弃队列最前面的任务,然后重新提交被拒绝的任务
* CallerRunsPolicy: 由调用线程(提交任务的线程)处理该任务
**/
ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(
2, //核心线程数
5,//最大线程数
3,// 多余空闲线程存活时间, 当线程池的线程数量超过corePoolSize,, 当空闲线程的空闲时间超过了 这个时间,多余的线程会被销毁,直到只剩下核心线程数量为止
TimeUnit.SECONDS,//空闲时间的单位
new ArrayBlockingQueue<>(3),//阻塞队列,
Executors.defaultThreadFactory(),//默认的线程工厂
new ThreadPoolExecutor.AbortPolicy());//拒绝策略 : 直接丢弃,抛异常
//new ThreadPoolExecutor.DiscardPolicy());
//new ThreadPoolExecutor.DiscardOldestPolicy());
//new ThreadPoolExecutor.CallerRunsPolicy()); //这个线程池拒绝策略生效: 当线程数量>=8 时候, 开始生效, =8的时候,拒绝策略已经生效,但是没有新的线程进来,所以不报异常 try {
for (int i = 1; i <= 6; i++) {
int stmp = i;
poolExecutor.execute(()->{
System.out.println(Thread.currentThread().getName() + "--线程--接待的客户为:" + stmp);
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
} catch (Exception e) {
e.printStackTrace();
} finally {
poolExecutor.shutdown();
}

运行结果: 核心线程为2, 最大线程数为5, 6个任务过来 , 2个任务直接执行, 3,4,5任务进入阻塞队列, 此时还有一个任务6, 且,队列满,正在运行的线程数为2, 所以此时新开一个线程,来执行任务6,而且任务6 这个是立即执行的

如果6个任务的基础上,是9个任务过来, 会发现正在运行的线程数为2, 队列中3个任务, 还有4个任务,且2<最大线程数5, 会创建3个线程,此时还有1个任务,所以此时会执行拒绝策略,由于采用的拒绝策略是abortPolicy, 所以直接抛异常

实际代码中我们都是使用的自定义线程池,这个参数,最大线程数是如何设置的?

答: 这里主要看自己的业务类型, 如果业务CPU型(就是说业务中计算的很多,而且是密集型计算,一计算内存就飙升), 线程数就设置为: cpu核数+1

如果业务是IO型,(就是说很多线程从数据库中取数据等等),这种情况下: 线程最大数就设置为: cpu核数 * 2

或者这样设置: cpu核数 / (1- 阻塞系数) 这个阻塞系数一般为0.8~0.9 如果取0.9, 线程数就为: cpu核数/0.1

JUC 并发编程--08,线程池,三大方法,七大参数,4种拒绝策略,代码演示的更多相关文章

  1. JUC之线程池-三大方法-七大参数-四种拒绝策略

    线程池:重点 三大方法 七大参数 四种拒绝策略 使用池化技术的理由: 我们的程序伴随着创建销毁线程十分浪费资源, 所以使用线程池,先创建线程,随用随取,用完归还 简单来说就是节约了资源. 使用线程池的 ...

  2. 并发编程 13—— 线程池的使用 之 配置ThreadPoolExecutor 和 饱和策略

    Java并发编程实践 目录 并发编程 01—— ThreadLocal 并发编程 02—— ConcurrentHashMap 并发编程 03—— 阻塞队列和生产者-消费者模式 并发编程 04—— 闭 ...

  3. Java并发编程:线程池的使用

    Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了, ...

  4. Java并发编程:线程池的使用(转)

    Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了, ...

  5. Java并发编程:线程池的使用(转载)

    转载自:https://www.cnblogs.com/dolphin0520/p/3932921.html Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实 ...

  6. Java并发编程:线程池的使用(转载)

    文章出处:http://www.cnblogs.com/dolphin0520/p/3932921.html Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实 ...

  7. [转]Java并发编程:线程池的使用

    Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了, ...

  8. 《转载》Python并发编程之线程池/进程池--concurrent.futures模块

    本文转载自Python并发编程之线程池/进程池--concurrent.futures模块 一.关于concurrent.futures模块 Python标准库为我们提供了threading和mult ...

  9. 【转】Java并发编程:线程池的使用

    Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了, ...

随机推荐

  1. UVA11248 网络扩容(枚举割边扩充)

    题意:      给你一个有向图,问你从1到n的最大流是多少?如果流量大于等于C那么直接输出一个串,否则输出只扩充一条边的流量就可以达到1->n大于等于C的所有边,如果扩充不了就输出另一个串.S ...

  2. Windows 驱动加载程序代码

    #include <windows.h> #include <winsvc.h> #include <conio.h> #include <stdio.h&g ...

  3. Intel汇编语言程序设计学习-第六章 条件处理-中

    6.3  条件跳转 6.3.1  条件结构 在IA-32指令集中没有高级的逻辑结构,但无论多么复杂的结构,都可以使用比较和跳转指令组合来实现.执行条件语句包括两个步骤:首先,使用CMP,AND,SUB ...

  4. 接口测试的N中玩法

    在我看来接口测试相对其他类型的测试是比较简单的.对于最常见的HTTP接口,只需要知道接口的 URL.方法.参数类型.返回值 ... 就可以对接口进行测试了. apifox 如果你是入门级选手,那么ap ...

  5. 学习Python一年,这次终于弄懂了浅拷贝和深拷贝

    官方文档:copy主题 源代码: Lib/copy.py 话说,网上已经有很多关于Python浅拷贝和深拷贝的文章了,不过好多文章看起来还是决定似懂非懂,所以决定用自己的理解来写出这样一篇文章. 当别 ...

  6. FastDFS依赖无法导入

    FastDFS依赖无法导入 fastdfs-client-java 导入爆红 <!-- FastDFS--> <dependency> <groupId>org.c ...

  7. COS 数据湖最佳实践:基于 Serverless 架构的入湖方案

    01 前言 数据湖(Data Lake)概念自2011年被推出后,其概念定位.架构设计和相关技术都得到了飞速发展和众多实践,数据湖也从单一数据存储池概念演进为包括 ETL 分析.数据转换及数据处理的下 ...

  8. Node.js核心模块API之文件操作

    参考:https://www.runoob.com/nodejs/nodejs-fs.html 异步I/O 1,文件操作 2,网络操作 在浏览器中也存在异步操作 1,定时任务 2,事件处理 3,Aja ...

  9. [bug] redis-cli连接时出现Could not connect to Redis at 127.0.0.1:6379: Connection refused

    参考 https://www.geek-share.com/detail/2684728161.html

  10. netperf对比

    netperf -H 10.1.60.141 -t TCP_STREAM -l 60  -p 10082 netperf -H 10.1.60.141 -t UDP_STREAM -l 60  -p ...