先来看下下面这段测试代码
- 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模式