生产上遇到很多并发问题,有很多是在编码阶段就可以避免的,总结一些需要考虑的要点如下:
- 使用并发的常见场景为针对大数据量遍历处理,考虑性能,采用并发处理。这是CPU密集型任务场景,同时出现多个任务时,性能不见得最优。
- 并发也有开销,不建议无脑并发。并发后堆栈会丢失,不方便排查问题。
- 异步开发模式具有传染性,比如使用可回调 Future 后,如果想要避免阻塞问题,需要使用map、flatMap语义。折中的方法是参考结构化并发,在必要位置等待,获取结果后清理资源。
- 需要注意副作用,尽量不要使用副作用。尽量不要修改共享的内容,比如本地缓存。
- 使用线程安全类 + 原子方法, ConcurrentHashMap 和 HashMap 相比,性能差别不大,而且内存占用基本一致,很多情况下可以直接替换。灵活使用 merge、computeIfAbsent 等方法,比如需要择优的场景,不需要重复写写命令式的逻辑。
- 考虑单次加载实现
- ConcurentHashMap 高并发时,可能有阻塞等待同一个桶位的问题,必须指定初始大小。
- 考虑线程池阻塞队列消费速度,防止某些捣蛋线程。
- 考虑处理拒绝任务异常,设计 fallback 策略。
- 并发超时或者任务取消时很容易出现线程泄露。
- 监控并发收益。
- 监控阻塞线程,防止惊群效应。