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