读书人

一路关于Java类初始化的难题

发布时间: 2011-12-17 23:37:33 作者: rapoo

一道关于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();    }} 

读书人网 >J2SE开发

热点推荐