多线程调优

上下文切换是什么

  • 分时系统中,一个线程被暂停剥夺使用权,另外一个线程被选中开始或者继续运行的过程就是上下文切换。
  • 一个线程的状态由 RUNNING 转为 BLOCKED ,再由 BLOCKED 转为 RUNNABLE ,然后再被调度器.选中执行,这就是一个上下文切换的过程。

线程生命周期

线程主要有“新建”(NEW)、“就绪”(RUNNABLE)、“运行”(RUNNING)、“阻塞”(BLOCKED)、“死亡”(DEAD)五种状态。到了 Java 层面它们都被映射为了 NEW、RUNABLE、BLOCKED、WAITING、TIMED_WAITING、TERMINADTED 等 6 种状态(见java.lang.Thread.State)。

  • java的RUNABLE对应于OS的RUNNABLE,RUNNING,BLOCKED状态。例如IO阻塞在java中也是RUNABLE状态。因为Java的线程状态是服务于监控的
  • 只有synchronized会导致java线程阻塞
  • Thread.sleep,Object.wait,Thread.join,LockSupport.parkNanos,LockSupport.parkUntil会导致java线程进入等待
    在这里插入图片描述

上下文切换的诱因

  • 程序本身触发的切换
  • 由系统或者虚拟机诱发的非自发性上下文切换

切换过程的主要开销

  • 操作系统保存和恢复上下文
  • 调度器进行线程调度
  • 处理器高速缓存重新加载
  • 上下文切换也可能导致整个高速缓存区被冲刷,从而带来时间开销

Synchronized和Lock对比

从性能方面上来说,在并发量不高、竞争不激烈的情况下,Synchronized 同步锁由于具有分级锁的优势,性能上与 Lock 锁差不多;但在高负载、高并发的情况下,Synchronized 同步锁由于竞争激烈会升级到重量级锁,性能则没有 Lock 锁稳定。
在这里插入图片描述

容器选择

在这里插入图片描述

多线程优化

竞争锁优化
  • 减少锁的时间
  • 降低锁的力度
    • 锁分离(读写锁)
    • 锁分段(里尔Java1.8 之前版本的 ConcurrentHashMap)
  • 非阻塞乐观锁替代竞争锁
优化 wait/notify 的使用,减少上下文切换
合理地设置线程池大小

先根据业务类型选择公式计算后再结合压测进行调整。我们要提高线程池的处理能力,一定要先保证一个合理的线程数量,也就是保证 CPU 处理线程的最大化。在此前提下,我们再增大线程池队列,通过队列将来不及处理的线程缓存起来。在设置缓存队列时,我们要尽量使用一个有界队列,以防因队列过大而导致的内存溢出问题。

  • CPU 密集型任务:线程数设置为N+1.CPU 核心数多出来的一个线程是为了防止线程偶发的缺页中断,或者其它原因导致的任务暂停而带来的影响
  • I/O密集型任务:线程数设置为2N.
使用协程实现非阻塞等待
减少 Java 虚拟机的垃圾回收

参考资料

  • https://my.oschina.net/goldenshaw/blog/705397
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值