2019年互联网(1.9)
一.JUC多线程及并发包
1.9.线程池用过吗?生产上你是如何设置合理参数
线程池的拒绝策略
等待队列也已经排满了,再也塞不下新的任务了同时,线程池的max也到达了,无法接续为新任务服务这时我们需要拒绝策略机制合理的处理这个问题.
JDK内置拒绝策略
-
AbortPolicy(默认): 直接抛出RejectedException异常阻止系统正常运行
-
CallerRunPolicy: "调用者运行"一种调节机制,该策略既不会抛弃任务,也不会抛出异常,而是提交给主线程运行
-
DiscardOldestPolicy: 抛弃队列中等待最久的任务,然后把当前任务加入队列中尝试再次提交
-
DiscardPolicy: 直接丢弃任务,不予任何处理也不抛出异常.如果允许任务丢失,这是最好的拒绝策略
以上拒绝策略,均实现了
RejectExecutionHandler
接口你在工作中单一的/固定数的/可变你的三种创建线程池的方法,你用哪个多?超级大坑
答案是一个都不用,我们生产上只能使用自定义的
Executors中JDK给你提供了为什么不用?
参考阿里巴巴java开发手册 【强制】
线程资源必须通过线程池提供,不允许在应用中自行显式创建线程。
说明:使用线程池的好处是减少在创建和销毁线程上所消耗的时间以及系统资源的开销,解决资源不足的问题。如果不使用线程池,有可能造成系统创建大量同类线程而导致消耗完内存或者“过度切换”的问题。
【强制】线程池不允许使用Executors去创建,而是通过ThreadPoolExecutor的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。
说明:Executors返回的线程池对象的弊端如下:
1)FixedThreadPool和SingleThreadPool:允许的请求队列长度为Integer.MAX_VALUE,可能会堆积大量的请求,从而导致OOM。
2)CachedThreadPool和ScheduledThreadPool:允许的创建线程数量为Integer.MAX_VALUE,可能会创建大量的线程,从而导致OOM。
自定义线程池
public class MyThreadPoolDemo_1_8_2 { public static void main (String[] args) { System.out.println(Runtime.getRuntime().availableProcessors()); ExecutorService executorService = new ThreadPoolExecutor( 2, 5, 1, TimeUnit.SECONDS, new LinkedBlockingQueue <>(3), Executors.defaultThreadFactory(), new ThreadPoolExecutor.DiscardPolicy()); for (int i = 1; i <=9; i++) { executorService.execute(()->{ System.out.println(Thread.currentThread().getName()+" \t 来了"); }); } } }