为什么Java方法调用在这里如此昂贵?

时间:2016-02-15 09:16:37

标签: java

我有一个线程执行器实现,其中包装器的成本显得非常昂贵。有一个包装类Task,定义如下:

 class Task {
   public Runnable r;       
   public Task(Runnable r) {          
     this.r = r;                                                                   
   }  

   public void run() {       
     r.run();      
   }     

 List<task> taskList;

对于以下情况,运行时间约为800毫秒。

  for (Task t : taskList) {                                                 
           t.r.run();                 
    }

虽然对于以下情况,它是~7000ms。

 for (Task t : taskList) {        
           t.run();                                                              
 }

它不会孤立地发生,而是发生在执行程序的代码中。只是想知道是否有人暗示可能会发生什么?

对于此测试用例,传递的runnable是以下内容:

class Tester implements Runnable {                                                 
  int i;                                                                           

  public Tester(int i) {                                                           
    this.i = i;                                                                    
  }                                                                                

  @Override                                                                        
  public void run() {                                                              
    //System.out.println(i);                                                       
    for (int j = 0; j < 1000000; j++) {                                            
      i = j;                                                                       
    }                                                                              
  }                                                                                

  public int getI() {                                                              
    return i;                                                                      
  }  

供参考,代码可在github.com/sharvanath/TempThreadPool找到。运行ThreadPoolTest以获取执行结果。现在尝试更改ThreadPool.java的第41行并查看魔法。

1 个答案:

答案 0 :(得分:1)

请注意在java中进行微管理你必须使用一些技巧,因为jvm可以使用JIT编译器优化代码并执行许多你不了解的技巧,看起来像你的测试实际上并没有做所有必要的事情让JVM为你做这个工作。(你必须在测试前做好热身,在衬里中逃脱,死代码等等。)

开始的一个好点是阅读这个主题 - How do I write a correct micro-benchmark in Java?

另外,我建议您使用JMH框架进行此类测试,这些测试已经在其源代码中使用了很多示例。