线程池基础知识
2020-11-06 本文已影响0人
crossroads
- 为什么使用线程池,优势是什么?
1> 重用存在的线程,减少线程创建、消亡的开销,提高性能与相应速度。
2>提高线程的可管理性,使用线程池可以进行统一的分配、调优和监控。 - 线程池如何使用?
不用Executors来创建线程池,因为里面设置的核心线程数或者最大线程数是Integer.max_value,会导致OOM。 - 线程池几个重要参数介绍与 线程池底层工作原理
1>corePoolSize:核心池的大小,默认情况下,创建线程池后,线程池中的线程数为0,当有任务来之后,会创建一个线程去执行任务,当线程池中的线程数目达到corePoolSize后,会把到达的任务放到缓存队列中。【可以参考银行人工窗口排队的场景】
2>maximumPoolSize:线程池中最大线程数,表示在线程池中最多可以创建多少个线程。如果线程数大于等于corePoolSize且缓存队列已满,则创建并启动一个线程来执行新提交的任务。如果线程数超过这个参数且线程池内的阻塞队列已满,则根据拒绝策略来处理该任务,默认是直接抛出异常【最大线程就是银行的总窗口数,核心线程就是平常开的几个窗口,只有繁忙的时候开其他的窗口。】
3>keepAliveTime:表示线程没有任务执行时最多保持多久时间会终止。默认情况下,只有当线程池中的线程数大于corePoolSize时,达到时间则会终止,直至线程池中的线程数不超过corePoolSize。但是如果调用了allowCoreThreadTimeOut(boolean)方法,不大于corePoolSize时,该参数也会起作用,直至线程池中的线程数为0.【忙碌时期过去,长时间没人来的窗口就可以关闭了,对于特殊时期,整个银行一个人都没有,窗口允许全部关闭。】
4>unit:keepAliveTime的时间单位,从天到纳秒,7种静态属性,例如TimeUnit.DAYS
5>workQueue:一个阻塞队列,用来存储等待执行的任务,例如ArrayBlockingQueue、LinkedBlockingQueue、SynchronousQueue等
6>threadFactory:线程工厂,主要用来创建线程
7>handler: 表示当拒绝处理任务时的策略
补充
1>拒绝策略
ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常
ThreadPoolExecutor.DiscardPolicy: 丢弃任务,不抛出异常
ThreadPoolExecutor.DiscardOldestPolicy:丢弃最前面的任务,然后重新尝试执行任务
ThreadPoolExecutor.CallerRunsPolicy: 由调用线程(提交任务的线程)直接执行被丢弃的任务的。
2>任务缓存队列
ArrayBlockingQueue:基于数组的先进先出队列,创建时需指定大小
LinkedBlockingQueue:基于链表的先进先出队列,创建时无需指定大小
synchrononousQueue:这个队列比较特殊,它不会保存提交的任务,而是将直接新建一个线程来执行新来的任务。
PriorityBlockingQueue: 具有优先级的无限阻塞队列。 - 生产上如何设置合理参数
一般根据任务的类型来配置线程池大小,如果是CPU密集型任务,就需要尽量压榨CPU,参考值可以设为NCPU+1;如果是IO密集型任务,参考值可以设置为2*NCPU。具体的设置需要根据实际情况调整,观察任务运行情况和系统负载、资源利用率来进行适当调整。
来自https://blog.csdn.net/weixin_28760063/article/details/81266152