版权声明:本文为博主原创文章,未经博主允许不得转载。 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模式