1、线程池的使用
ThreadPoolExecutor的定义,几个核心参数
coreSize:核心线程数,
maxSize:最大线程数
keepAliveTime:大于coreSize的线程在空闲时的存活时间
ThreadFactory:一个方便识别的线程名字
RejectedExecutionHandler:拒绝策略,可以用日志记录
BlockQueue:阻塞队列,下面单独说明
整体逻辑:
执行execute或submit提交一个任务;
直接创建一个核心线程(线程数小于核心线程数);
加入到阻塞队列中(核心线程数已满);
创建线程执行(队列已满,无界队列,这个参数无效);
执行拒绝策略(达到最大线程数)。
线程数的大小根据任务是CPU密集(线程数不宜太大)还是IO密集(可以适当的调大一些)决定。
2、BlockingQueue的选择
有界(推荐使用):方便发现问题,对线程池的使用进行优化,调整到合适的参数
无界:如果使用无界队列,在线程池处理不过来的情况下,导致队列一直堆积,服务超时,导致内存溢出问题。
3、CountDownLatch的使用
初始化一个值,主线程会等待一组子线程都执行完成后继续,子线程完成会执行countDown
主线程(await、await带超时)进行等待。
如果使用await方法,在countDown不为0时会一直阻塞,会使任务停滞,推荐使用带超时的
4、CompletableFuture的使用
由线程池中的线程异步执行任务,可以异步获取结果。
获取异步线程的结果:join、get、get带超时;join和get都会无限制等待,推荐使用带超时的get
5、对于以上的使用的几点说明:
a、主要要根据自己的规则(业务或者交易量)做线程池隔离,不然当有不可控的原因导致部分交易超时,获取不到连接、数据库超时等,会导致整个服务都阻塞或者被拒绝。
b、对于线程数的大小要根据需求,调试最优值
c、阻塞队列推荐有界
d、CountDownLatch的使用要分区场景,感觉不是必须,还是慎用
e、对于获取异步线程的结果获取,一定要注意带超时,防止线程会一直阻塞,消耗资源
6、结束语
合理使用可以使代码飞起,使用不当就会深陷其中。