有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java模拟具有固定工作量的持续性任务

我正在模拟一个CPU受限的任务。每个CPU受限的任务计算800的阶乘。每个CPU绑定的任务都是线程执行的可运行对象。当我增加线程数(每个线程运行一个可运行的tak)时,我发现一些线程运行得非常快,以至于服务时间趋于零。我无法理解这种行为。代码如下

import java.math.BigInteger;    
public class CpuBoundJob  implements Runnable {     
    public void run() {    
         BigInteger factValue = BigInteger.ONE;
            long t1=System.nanoTime();      
            for ( int i = 2; i <= 800; i++){
              factValue = factValue.multiply(BigInteger.valueOf(i));
            }
        long t2=System.nanoTime();              
        System.out.println("Service Time(ms)="+((double)(t2-t1)/1000000));
    }    
}

public class TaskRunner extends Thread {
    CpuBoundJob job=new CpuBoundJob();
    public void run(){

    job.run();  
    }
}

public class Test {
int numberOfThreads=5;
public Test(){
    for(int i=1;i<=numberOfThreads;i++){
        TaskRunner t=new TaskRunner();
        t.start();
        }
}
public static void main(String[] args) {
    new Test(); 
    }
}

如果有5个线程,输出如下

Service Time(ns)=28.765821
Service Time(ns)=33.489663
Service Time(ns)=29.19727
Service Time(ns)=34.259404
Service Time(ns)=37.347448

如果有10个线程,输出如下

Service Time(ns)=45.647232
Service Time(ns)=3.972654
Service Time(ns)=23.494475
Service Time(ns)=12.210069
Service Time(ns)=19.382478
Service Time(ns)=15.34706
Service Time(ns)=54.769652
Service Time(ns)=20.646827
Service Time(ns)=3.28936
Service Time(ns)=29.809905
Service Time(ns)=60.798897
Service Time(ns)=50.718839
Service Time(ns)=2.727253
Service Time(ns)=2.882779
Service Time(ns)=63.864835
Service Time(ns)=42.601425
Service Time(ns)=4.029496
Service Time(ns)=4.339761
Service Time(ns)=79.396239
Service Time(ns)=2.923832
Service Time(ns)=5.773848
Service Time(ns)=3.064359
Service Time(ns)=2.446592
Service Time(ns)=2.205802
Service Time(ns)=2.212513
Service Time(ns)=2.265408
Service Time(ns)=82.51073
Service Time(ns)=2.200276
Service Time(ns)=2.289487
Service Time(ns)=2.322645
Service Time(ns)=2.201459
Service Time(ns)=2.217644
Service Time(ns)=2.197908
Service Time(ns)=2.252381
Service Time(ns)=13.564814
Service Time(ns)=2.238171
Service Time(ns)=2.199486
Service Time(ns)=2.179355
Service Time(ns)=2.237381
Service Time(ns)=2.593041
Service Time(ns)=2.444225
Service Time(ns)=2.42054
Service Time(ns)=38.745219
Service Time(ns)=81.232565
Service Time(ns)=19.612216
Service Time(ns)=22.31381
Service Time(ns)=59.521916
Service Time(ns)=59.511258
Service Time(ns)=54.439255
Service Time(ns)=11.582434

我无法理解2.4等的服务时间,有时服务时间降至0.8。为什么运行固定工作量的线程执行得如此之快


共 (3) 个答案

  1. # 1 楼答案

    你是怎么开始这些测试的?如果每次都冷启动它们,我怀疑JVM是“warming up”和Just In Time compiling代码。如果是这种情况,那么带有几个线程的测试将以解释代码的形式运行,随后的运行将被编译,甚至以后的运行也会根据以前的运行进行优化The JVM is magic that way

    降低优化影响的想法:

    • 使用随机数作为工作参数(而不是循环索引)
    • 将时间用作工作参数(同上)
    • 加入一些字符串连接
    • 根据工作参数改变回路的长度
  2. # 2 楼答案

    在某个时刻,JIT可能会启动并优化代码。尝试通过先“预热”系统来运行实验,即进行N次迭代(你需要试验N的最佳值),在不进行测量的情况下运行系统,然后进行测量,例如:

    public class Test {
    
    private int numberOfThreads;
    private int warmUpIterations;
    
    public Test(int numberOfThreads, int warmUpIterations) {
        this.numberOfThreads = numberOfThreads;
        this.warmUpIterations = warmUpIterations;
    }
    
    public void runTests() {
        for (int i = 0; i < warmUpIterations; i++) {
            test(); // don't collect timing here
        }
    
        test(); // collect timing here
    }
    
    private void test() {
        for (int i = 0; i < numberOfThreads; i++) {
            TaskRunner t = new TaskRunner();
            t.start();
        }
    }
    
    public static void main(String[] args) {
        new Test(10, 10000).runTests();
    }
    

    }

    还打印从{{CD1>}内的统计数据有问题,考虑将它们积聚在一些集合中,并在测试完成后打印它们。

  3. # 3 楼答案

    很可能是计时功能太不准确,无法测量如此快速的操作。试试100000的阶乘或类似的东西

    nanotime方法的文件称,它不能保证提供纳秒精度:

    This method provides nanosecond precision, but not necessarily nanosecond resolution (that is, how frequently the value changes) - no guarantees are made except that the resolution is at least as good as that of currentTimeMillis().