异步模式之工作线程--多线程设计模式

让有限的工作线程(Worker Thread)来轮流异步处理无限多的任务。也可以将其归类为分工模式,它的典型实现 就是线程池,也体现了经典设计模式中的享元模式(重用对象 这里是线程)。

注意,不同任务类型应该使用不同的线程池,这样能够避免饥饿,并且提高效率 。 比如说服务员(线程池A) 和厨师(线程池B)

 

饥饿现象:

两个能点餐做饭的服务员,同时来两个客人 ,都去点餐,则没人做饭,假设要点餐服务员要等待饭做好,才能服务,则可能造成饥饿。

比较像死锁 ,也可以理解为线程不足导致的饥饿现象。

一个代码块可以正常运行 相当于分开任务  两个代码块都去处理点餐去了。用jconsole无法检测出死锁

 

 

 解决方法可以增加线程池的大小,不过不是根本解决方案,还是前面提到的,不同的任务类型,采用不同的线程 池

 

问题:创建多少线程合适?

过小会导致程序不能充分地利用系统资源、容易导致饥饿

过大会导致更多的线程上下文切换,占用更多内存 。

应该根据应用程序的类型来考虑

CPU 密集型运算

通常采用 cpu 核数 + 1 能够实现最优的 CPU 利用率,+1 是保证当线程由于页缺失故障(操作系统)或其它原因 导致暂停时,额外的这个线程就能顶上去,保证 CPU 时钟周期不被浪费 

I/O 密集型运算
CPU 不总是处于繁忙状态,例如,当你执行业务计算时,这时候会使用 CPU 资源,但当你执行 I/O 操作时、远程

RPC 调用时,包括进行数据库操作时,这时候 CPU 就闲下来了,你可以利用多线程提高它的利用率。 经验公式如下

线程数 = 核数 * 期望 CPU 利用率 * 总时间(CPU计算时间+等待时间) / CPU 计算时间

计算CPU占用 可以使用一些工具 去监控,后期调优

 

正确处理线程池中的异常

1.使用try catch()捕捉   2.使用future 和callable 拿到异常

 

结论 :

工作线程模式 应该正确处理饥饿现象。我们应当,针对不同的任务类型,采用不同的线程池。创建多少线程 , 应该根据应用程序使用CPU的频率来judge

 

 

 

 

 

 

 

 

posted @ 2022-03-27 00:29  贪、欢  阅读(70)  评论(0)    收藏  举报