9.线程池用过吗?生产上你如何设置合理参数
说明
本文目录前是相关视频的名字和具体视频中思维导图的名字
题目
9.线程池用过吗?生产上你如何设置合理参数
51 线程池的4种拒绝策略理论简介
线程池的拒绝策略你谈谈
是什么
等待队列也已经排满了,再也塞不下新任务了
同时,
线程池中的max线程也达到了,无法继续为新任务服务。
这时候我们就需要拒绝策略机制合理的处理这个问题。
JDK内置的拒绝策略
- AbortPolicy(默认):直接抛出 RejectedExecutionException异常阻止系统正常运行。
- CallerRunsPolicy:"调用者运行"一种调节机制,该策略既不会抛弃任务,也不会抛出异常,而是将某些任务回退到调用者,从而降低新任务的流量
- DiscardoldestPolicy:抛弃队列中等待最久的任务,然后把当前任务加入队列中尝试再次提交当前任务。
- DiscardPolicy:直接丢弃任务,不予任何处理也不抛出异常。如果允许任务丢失,这是最好的一种方案。
以上内置拒绝策略均实现了RejectedExecutionHandler 接口
52 线程池实际中使用哪一个
×你在工作中单一的固定数的/可变的三种创建线程池的方法,你用那个多?超级大坑
答案是一个都不用,我们生产上只能使用自定义的
Executors中JDK已经给你提供了,为什么不用?
阿里巴巴Java开发手册
3.【强制】线程资源必须通过线程池提供,不允许在应用中自行显式创建线程。
说明: 使用线程池的好处是减少在创建和销毁线程上所消耗的时间以及系统资源的开销,解资源不足的问题。如果不使用线程池,有可能造成系统创建大量同类线程而导致消耗完内存:者“过度切换”的问题。
4.【强制】线程池不允许使用Executors 去创建,而是通过ThreadPoolExecutor的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。
说明: Executors返回的线程池对象的弊端如下:
- FixedThreadPool和singleThreadPool:
允许的请求队列长度为Integer.MAX_VALUE,可能会堆积大量的请求,从而导致OOM。 - cachedThreadPool和 scheduledThreadPool:
允许的创建线程数量为Integer.MAX_VALUE,可能会创建大量的线程,从而导致OOM。
53 线程池的手写改造和拒绝策略
你在工作中是如何使用线程池的。是否自定义过线程池使
Case
package threadpool8;
import java.util.concurrent.*;
/**
* @author CSDN@日星月云
* @date 2022/10/10 21:26
* 第4种获得使用Java多线程的方式,线程池
*/
public class MyThreadPoolDemo {
public static void main(String[] args) {
ExecutorService threadPool=new ThreadPoolExecutor(
2,
5,
1L,
TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>(3),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.DiscardPolicy());
try {
//模拟10个用户开办理业务,每一个用户就是一个来自外面的请求线程
for (int i = 1; i <= 9; i++) {
threadPool.execute(()->{
System.out.println(Thread.currentThread().getName()+"\t 办理业务");
//tsleep
try{ TimeUnit.MILLISECONDS.sleep(200); }catch (InterruptedException e){ e.printStackTrace(); }
});
}
} catch (Exception e) {
e.printStackTrace();
} finally {
threadPool.shutdown();
}
}
/**
* AbortPolicy 异常阻止系统正常运行 RejectedExecutionException
* CallerRunsPolicy 任务回退到调用者 main 办理业务
* DiscardOldestPolicy 抛弃队列中等待最久的任务
* DiscardPolicy 直接丢弃任务 8个,丢一个
*/
public static void threadPoolInit() {
//...
}
}
54 线程池配置合理线程数
合理配置线程池你是如何考虑的?
CPU密集型
CPU密集的意思是该任务需要大量的运算,而没有阻塞,CPU一直全速运行。CPU密集任务只有在真正的多核CPU上才可能得到加速(通过多线程),
而在单核CPU上:(悲剧吧?),无论你开几个模拟的多线程该任务都不可能得到加速,因为CPU总的运算能力就那些。
CPU密集型任务配置尽可能少的线程数量:
一般公式:CPU核数+1个线程的线程池
IO密集型
1
由于IO密集型任务线程并不是一直在执行任务,则应配置尽可能多的线程,如CPU核数 * 2
2
IO密集型,即该任务需要大量的IO,即大量的阻塞。
在单线程上运行IO密集型的任务会导致浪费大量的CPU运算能力浪费在等待。
所以在I0密集型任务中使用多线程可以大大的加速程序运行,即使在单核CPU上,这种加速主要就是利用了被浪费掉的阻塞时间。
IO密集型时,大部分线程都阻塞,故需要多配置线程数:
参考公式:CPU核数 / 1-阻塞系数 阻塞系数在0.8~0.9之间
比如8核CPU:8 / 1 - 0.9= 80个线程数