JAVA语言的线程,从规范的角度来说是不强制要求任何具体的实现方式的。采用1:1、N:1、M:N模型都可以。
具体到我们平时常用的JVM实现,Oracle/Sun的HotSpot VM,它是用1:1模型来实现Java线程的,也就是说一个Java线程是直接通过一个OS线程来实现的,中间并没有额外的间接结构。而且HotSpot VM自己也不干涉线程的调度,全权交给底下的OS去处理。所以如果OS想把某个线程调度到某个CPU/核上,它就自己弄了。
这个意义上说Java程序跑在HotSpot VM上开多个Java线程,就跟一个C/C++程序开了多线程来跑没有任何两样。那么怎么控制这些线程分布到不同的CPU核上去呢?
在linux上的话,可以用taskset来把线程绑在某个指定的核上。在Java层面上,有大大写了个现成的库来利用taskset绑核:OpenHFT/Java-Thread-Affinity 有兴趣的话可以参考一下。
通过taskset,我们可以更加有效地利用CPU资源。我们可以把一些不太重要的比如copy/备份/同步等工作限定在一颗cpu上,或者是多核的cpu的一颗核心上进行处理,虽然这不一定是最有效的方法,但可以最大程度上利用了有效资源,降低那些不太重要的进程占用cpu资源;
查看系统下cpu信息:
#cat /proc/cpuinfo
taskset就可以帮我们完成这项工作,而且操作非常简单;
该工具系统默认安装,rpm包名util-linux
#taskset --help
taskset (util-linux 2.13-pre7)
usage: taskset [options] [mask | cpu-list] [pid | cmd [args...]]
set or get the affinity of a process
-p, –pid operate on existing given pid
-c, –cpu-list display and specify cpus in list format
-h, –help display this help
-v, –version output version information
举例:
1、开启一个只用0标记的cpu核心的新进程(job.sh是你的工作脚本)
#taskset -c 0 sh job.sh
2、查找现有的进程号,调整该进程cpu核心使用情况(23328举例用的进程号)
#taskset -pc 0 23328
pid 23328's current affinity list: 0-3 #0-3表示使用所有4核进行处理
pid 23328's new affinity list: 0 #调整后改为仅适用0标记单核处理
3、可在top中进行负载check
最后你可以在你的工作脚本中加入该指令来合理利用现有的cpu资源;