原创

Go如何设置使用的CPU个数

Go语言天生支持高并发,其中一个体现就是如果你的Go程序不设置并发时使用的最大cpu核数的话,在高并发情况下Go会自动把所有CPU都用上,跑满。

拓展阅读:
我们简单理解一下cpu(懂得可以跳过)
举例:比如有一个专门做财务的公司(计算机),他们的赚钱业务很简单(计算机工作),就是帮别人做算术题(计算机工作的具体任务),加减乘除之类的算术题,现在公司有4个员工(物理意义上的4个cpu核数),有4本算数书(4个进程),每本书有10道题(线程),一共有40道算术题要算(40个线程任务),于是4个人一起干活,在同一时间,有4道算术题被计算,最后大致上每个人算了10道算数题。
第二天,有8本算术书(8个进程),他们为了快速完成任务,规定一人(每个人是一个物理cpu核数)管2本算数书(单物理cpu内部实际上是管理的两个不同的算数书,也就是相当于有两个不同的逻辑cpu),为的就是如果第一本做烦了可以换着做第2本,混合着做,最后都做完就可以。

cpu是进行最终二进制计算的核心计算器,cpu核数是有两个概念,一个是真实世界的物理硬件核数,比如4核cpu,就是有4个物理硬件内核,然而我们在生产环境的linux服务器上top的时候,出现的cpu个数实际上是逻辑cpu数,有可能linux服务器只有4核物理cpu,可是每个物理cpu分为两个逻辑cpu,这个时候我们在linux上top看的时候就是有8个cpu信息行数据。

我们回顾一下Java,Java运行时我们一般管理的都是线程数,而所有的java线程均在JVM这个虚拟机进程中,于是在高并发情况下,当cpu资源充足时,我们需要根据cpu的逻辑核数来确定我们的线程池线程数(在高并发环境下一定要设置优化线程数啊!!!线程池就能设置线程数!!!),比如我们是4个物理cpu,每个双核逻辑,一共逻辑八核cpu,此时,比如我们要做并发定时任务,这台服务器没有其它程序,8个cpu全都给我们自己用,那么我们的线程数最少也要设置成8,再细化,我们得根据程序执行的任务分别在cpu计算(正常处理程序业务逻辑)的耗时和cpuIO耗时(IO耗时比如查mysql数据库数据),假如我们定时跑批任务一个任务计算用时0.2秒,查数据库0.8秒(自己可以写程序监测),那么可以参考如下公式:
总任务耗时/cpu耗时 = 多少个线程(每个逻辑cpu)

我们算出每个逻辑cpu要跑多少个线程后再乘以逻辑cpu的个数,就能算出来了

如下:
(0.2+0.8)/0.2=5个线程(每个逻辑cpu)
5*8 = 40
于是我们在线程池的时候应该这么写:
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(40);

至于公式为什么要这么写,是因为IO操作的时候,cpu是空闲的,也就是说,0.8秒数据库操作的时候,cpu都是空闲的,那么我们就多开几个线程让cpu在这0.8秒的时候工作,开几个呢,要等0.8秒,一个任务cpu要计算0.2秒,0.8/0.2=4(个),可是这个逻辑cpu还有一个主线程在那0.8秒上等着结果呢,所以是4+1=5(个)线程。

本文链接地址:http://www.ysxbohui.com/article/236

正文到此结束