一直以来都很相信,多线程程序在多核情况下比单线程程序有更优化的系统压力表现。
一直以来也都没有具体的数据支持,这个优化的表现到底有多好的情况。
今天,写了一个短小的程序,分别在xeon E5310 和core2 T5270上跑了一下,看到的结果很出乎我的预料。
我的测试方法是这样的,首先,启动若干个线程,各线程执行若干时间的简单程序,在线程执行结束以后,等待若干时间后,使用单线程执行这个简单程序,在windows系统下,打开任务管理器的性能标签,根据执行期内的性能占用情况分析线程与多核处理器下的性能分解的关系。这个测试分别用10线程和100线程进行了测试。测试结果的截图是这样的:
core2 测试
xeon 10 线程测试
xeon 100 线程测试
在上图中,第一张图片是core2的测试,core2的测试中,10线程和100线程的cpu占用情况是一致的,无论单线程和多线程,双核都被占用了80%以上的cpu。两个cpu核心最左边的一个小高峰是打开任务管理器时造成的,中间的高峰是多线程测试的结果,两个cpu核心右边的高峰时单线程测试的结果。
第二张图片是xeon下10线程测试的结果,各cpu核心最左边的高峰是多线程测试的结果,两个cpu核心右边的高峰时单线程测试的结果。cpu核心表现中多线程测试占用了3个cpu核心,单线程测试中主要占用了2个cpu核心(中间间隔时间较短,且中间有其他线程性能干扰,第二个核心表现几乎连在一起了),最后一个处理器略有反应,单不明显。
第三张图片是xeon下100线程的测试结果,处理器的表现于10线程下的表现基本一致(不同在原来多占用2、3核心,现在占用3、4核心)
所以,我认为初步预计,多线程程序设计对intel的cpu下有帮助,但考虑到多线程本身压力大于单线程,排除cpu由于系统运算压力自主分配的因素外,java的多线程设计对程序压力分解的帮助不如想象中的明显,这可能与cpu的线程压力分配策略有关。
另外,这个测试仅在windows下对intel的两种cpu进行了测试,其他情况不好预计,希望有机会能给补充进来。
最后,附上我的测试代码:
package com.icefox.test.mulcore;
import java.util.Date;
/**
* 为测试多线程在多核,多cpu下的表现
* 准备多线程程序长时间运行,然后查看系统性能,看看是否占用多个cpu平均分配
* jdk为1.5
*
* 结论:
* 在双核intel core2 5270 1.4G处理器上测试,
* 使用10线程和100线程测试,结果一致
* 无论单线程还是多线程,反应类似,预计为没有为多线程做处理
* (结果截图在MulCoreTest_core_thread100.JPG)
*
* 在四核双路intel xeon E5310 处理器上使用10线程和100线程测试,
* 多线程占用3核心运算,单线程占用2核心运算
* 预计为多线程对分处理器有帮助,但cpu分配不完全依赖线程,
* 即使单线程,cpu仍可依照一定算法进行分配
* (结果截图在MulCoreTest_xeon_thread10.JPG
* MulCoreTest_xeon_thread100.JPG)
*
* 总结:
* 初步预计,多线程程序设计对intel的cpu下有帮助,
* 但排除cpu由于线程压力自主分配的因素外,
* java的多线程设计对程序压力分解的帮助不如想象中的明显,
* 这可能与cpu的线程压力分配策略有关。
* @author wjx
*
*/
public class MulCoreTest {
private int continueSecond; // 线程持续时间,默认20秒
public MulCoreTest(){
continueSecond=20;
}
public MulCoreTest(int continueSecond){
this.continueSecond = continueSecond;
}
public int getContinueSecond(){
return this.continueSecond;
}
/**
* 线程测试方法,先执行指定时间的多线程,
* 再执行指定时间的单线程,
* 查看资源管理器,证明线程与cpu核心的关系
* @throws InterruptedException
*/
public void testThread() throws InterruptedException{
/**
* 多线程执行
*/
System.out.println("Mul Thread run");
for(int i=0;i<100;i++){
new CustThread().start();
}
/**
* 休息30秒
*/
Thread.sleep((this.continueSecond+30)*1000);
/**
* 单线程执行
*/
System.out.println("Single Thread run");
testSingleThread();
}
/**
* @param args
* @throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException {
// TODO Auto-generated method stub
MulCoreTest mul = new MulCoreTest();
mul.testThread();
}
/**
* 单线程测试
*
*/
public void testSingleThread(){
Date startTime = new Date();
while(true){
System.out.println("Single Thread");
Date nowTime = new Date();
if((nowTime.getTime()-startTime.getTime())/1000>continueSecond){
break;
}
}
}
}
package com.icefox.test.mulcore;
import java.util.Date;
/**
* 一个定制的线程
* @author wjx
*
*/
public class CustThread extends Thread {
private int continueSecond; // 线程持续时间,单位:秒
public CustThread(){
continueSecond=20;
}
public CustThread(int continueSecond){
this.continueSecond = continueSecond;
}
public void run(){
Date startTime = new Date();
while(true){
System.out.println("Mul Thread Run:"+this.getId());
Date nowTime = new Date();
if((nowTime.getTime()-startTime.getTime())/1000>continueSecond){
break;
}
}
}
}