Java的多线程应用

161 阅读2分钟

1、线程池的使用

ThreadPoolExecutor的定义,几个核心参数
coreSize:核心线程数,
maxSize:最大线程数
keepAliveTime:大于coreSize的线程在空闲时的存活时间
ThreadFactory:一个方便识别的线程名字
RejectedExecutionHandler:拒绝策略,可以用日志记录
BlockQueue:阻塞队列,下面单独说明

整体逻辑:
	执行execute或submit提交一个任务;
	直接创建一个核心线程(线程数小于核心线程数);
    加入到阻塞队列中(核心线程数已满);
    创建线程执行(队列已满,无界队列,这个参数无效);
    执行拒绝策略(达到最大线程数)。
    
线程数的大小根据任务是CPU密集(线程数不宜太大)还是IO密集(可以适当的调大一些)决定。

2、BlockingQueue的选择

有界(推荐使用):方便发现问题,对线程池的使用进行优化,调整到合适的参数
无界:如果使用无界队列,在线程池处理不过来的情况下,导致队列一直堆积,服务超时,导致内存溢出问题。

3、CountDownLatch的使用

初始化一个值,主线程会等待一组子线程都执行完成后继续,子线程完成会执行countDown
主线程(awaitawait带超时)进行等待。

如果使用await方法,在countDown不为0时会一直阻塞,会使任务停滞,推荐使用带超时的

4、CompletableFuture的使用

由线程池中的线程异步执行任务,可以异步获取结果。
获取异步线程的结果:joingetget带超时;joinget都会无限制等待,推荐使用带超时的get

5、对于以上的使用的几点说明:

a、主要要根据自己的规则(业务或者交易量)做线程池隔离,不然当有不可控的原因导致部分交易超时,获取不到连接、数据库超时等,会导致整个服务都阻塞或者被拒绝。
b、对于线程数的大小要根据需求,调试最优值
c、阻塞队列推荐有界
d、CountDownLatch的使用要分区场景,感觉不是必须,还是慎用
e、对于获取异步线程的结果获取,一定要注意带超时,防止线程会一直阻塞,消耗资源

6、结束语

合理使用可以使代码飞起,使用不当就会深陷其中。