Java Math.random()导致主线程假死(?)

来源:互联网 发布:nginx 访问index.php 编辑:程序博客网 时间:2024/06/14 04:41

先来看下下面这段测试代码

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. public class Run {  
  2.     public static void main(String[] args) throws InterruptedException {  
  3.         Thread2 b = new Thread2();  
  4.         b.setName("t1");  
  5.         b.start();  
  6.                 Thread.sleep(2000);  
  7.                 System.out.println("main finished");  
  8.     }  
  9. }  
  10.   
  11. class Thread1 extends Thread {  
  12.     @Override  
  13.     public void run() {  
  14.         for (int i = 0; i < Integer.MAX_VALUE; i++) {  
  15.             String newString = new String();  
  16.             Math.random();  
  17.         }  
  18.     }  
  19.   
  20. }  
  21.   
  22. class Thread2 extends Thread {  
  23.     @Override  
  24.     public void run() {  
  25.         try {  
  26.             Thread1 a = new Thread1();  
  27.             a.start();  
  28.             System.out.println("begin join " + Thread.currentThread().getName());  
  29.             a.join();  
  30.             System.out.println("end join");  
  31.         } catch (InterruptedException e) {  
  32.             e.printStackTrace();  
  33.         }  
  34.     }  
  35. }  
运行main函数后,正常来说一定会在2秒(main中sleep的时间)后输出下面的结果

[html] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. begin join t1  
  2. main finished  
但是等了很久,只输出了begin join t1,而main函数迟迟没有结束


分析

在Thread1启动后,几乎所有的cpu时间片都花费在Math.random()这行上,而没有时间回到主线程

所以,解决方法是:让CPU除了生产随机数,再做点其他事情,让主线程得到机会运行

简单修改一下代码,原先new String没有传参数,JVM可能会认为是无效代码不做处理,这是-server模式下的一个优化,现在加了参数,JVM认为需要开辟内存,在这个过程中,CPU时间片被拆分,分给了主线程

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. String newString = new String("" + i);  
现在再次运行,发现可以正常输出main finished了,当然实际开发过程中,也可以使用其他方式去拆分CPU时间片


本案例基于JDK1.8u91 server模式

0 0
原创粉丝点击