日期:2014-05-20  浏览次数:20661 次

一道关于Java类初始化的难题
请看下面两个程序:
(1)
public class InitPuzzle {
  private static boolean initialized = false;
  private static Thread t = new Thread(new Runnable() {
  public void run() {
  System.out.println(Thread.currentThread());
  initialized = true;
  }
  });

  static {
  t.start();
  System.out.println(Thread.currentThread());
  
  try{
  Thread.sleep(1000);
  System.out.println(initialized);
  }catch (InterruptedException e){
  throw new AssertionError(e);
  }
  }

  public InitPuzzle(){
  System.out.println("Initialization is finished!");
  }

  public static void main(String[] args){
  new InitPuzzle();
  }
}

=============================================

(2)

public class InitPuzzle {
  private boolean initialized = false;
  private Thread t = new Thread(new Runnable() {
  public void run() {
  System.out.println(Thread.currentThread());
  initialized = true;
  }
  });

  {
  t.start();
  System.out.println(Thread.currentThread());
  
  try{
  Thread.sleep(1000);
  System.out.println(initialized);
  }catch (InterruptedException e){
  throw new AssertionError(e);
  }
  }

  public InitPuzzle(){
  System.out.println("Initialization is finished!");
  }

  public static void main(String[] args){
  new InitPuzzle();
  }
}

这两个类的差别只在前者多了static,但是运行输出结果为什么不一样呢?

------解决方案--------------------
我想LZ困惑的是第一个事例代码,因为初始线程等待1000毫秒的目的是让t先执行
完毕。并且从结果来看t确实很快的启动了(初始线程的打印后立即出现了t线程的
打印,然后大概1秒的时间打印出“false”。看起来t线程对“initialized”的
修改无效。

首先要说明这个地方和对象的初始化无关,如果我们把main函数中的代码改为如下:
try{
Class.forName("InitPuzzle");
}catch (Exception e){

}

这里没有实例化对象,只是加载了类,执行的结果除了没有构造函数里面的打印外其他都一样

为了找到问题,把t线程修改一下,在修改 initialized 后加一个打印

private static Thread t = new Thread(new Runnable() {
public void run() {
System.out.println("t:" + Thread.currentThread());
initialized = true;
System.out.println("u:" + initialized);
}
});

执行结果为

Thread[main,5,main]
t:Thread[Thread-0,5,main]
false
u:true

“U:true”说明t线程的修改是成功的,但它却出现了在“false”后面。
所以执行流程变成了 “初始线程” -〉t线程 -〉“初始线程” -〉t线程,看来t线程在执行
initialized = true;时被阻塞住了。你可以增大初始线程sleep的时间,结果不受影响。
只是为什么被“阻塞”我也不能解释。
------解决方案--------------------
把程序改成这样试了一下
Java code

public class InitTest {
    private static boolean initialized = false;
    private static int initI = 0;
    private static Thread t = new Thread(new Runnable() {
        public void run() {
            System.out.println("1");
            initI = 2;
            System.out.println(initI);
        }
    });

    static {
        t.start();
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            throw new AssertionError(e);
        }
        System.out.println(initialized);

    }

    public InitTest() {
        System.out.println("Initialization is finished!");
    }

    public static void main(String[] args) {
        new InitTest();
    }
}