【分析】Java Math.random()导致主线程假死

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/opensure/article/details/51671394

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

public class Run {
	public static void main(String[] args) throws InterruptedException {
		Thread2 b = new Thread2();
		b.setName("t1");
		b.start();
                Thread.sleep(2000);
                System.out.println("main finished");
	}
}

class Thread1 extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < Integer.MAX_VALUE; i++) {
            String newString = new String();
            Math.random();
        }
    }

}

class Thread2 extends Thread {
    @Override
    public void run() {
        try {
            Thread1 a = new Thread1();
            a.start();
            System.out.println("begin join " + Thread.currentThread().getName());
            a.join();
            System.out.println("end join");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
运行main函数后,正常来说一定会在2秒(main中sleep的时间)后输出下面的结果

begin join t1
main finished
但是等了很久,只输出了begin join t1,而main函数迟迟没有结束


分析

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

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

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

String newString = new String("" + i);
现在再次运行,发现可以正常输出main finished了,当然实际开发过程中,也可以使用其他方式去拆分CPU时间片


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





猜你喜欢

转载自blog.csdn.net/opensure/article/details/51671394
今日推荐