请看下面两个程序:
(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,但是运行输出结果为什么不一样呢?
(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,但是运行输出结果为什么不一样呢?
private static boolean initialized = false;
private static Thread t = new Thread(new Runnable() {
public void run() {
System.out.println("1");
initialized = true;
System.out.println("2");
}
}); static {
t.start();
System.out.println("3"); 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();
}
}
//运行多次会有输出结果顺序会不同:
//3
//1
//false
//2
//Initialization is finished!虽然不明白,但运行多几次就可以看出 是先打印System.out.println(initialized) 再执行initialized = true的第二个程序public class InitPuzzle2 {
private boolean initialized = false;
private Thread t = new Thread(new Runnable() {
public void run() {
System.out.println("1");
initialized = true;
System.out.println("2");
}
}); {
t.start();
System.out.println("3"); try{
Thread.sleep(1000);
System.out.println(initialized);
}catch (InterruptedException e){
throw new AssertionError(e);
}
} public InitPuzzle2(){
System.out.println("Initialization is finished!");
} public static void main(String[] args){
new InitPuzzle2();
}
}
输出结果为
3
1
2
true
Initialization is finished!前面312一下就执行打印了可见initialized 已被设为true
private static boolean initialized = true;
这样每次都是true还是期待高人说明
书94页
5.7.1初始化顺序中提到:
在类的内部,变量定义的先后顺序决定了初始化的顺序。即使变量定义散步于方法定义之间,它们仍旧会在任何方法(包括构造器)被调用之前得到初始化。5.7.2静态数据的初始化中提到:
书96页第三自然段
初始化的顺序是先静态对象,而后是非静态对象。class Window
{
Window(int er)
{
System.out.println("Window(" + er + ")");
}
}class House
{
Window w1 = new Window(1);
House()
{
System.out.println("House()");
w3 = new Window(33);
}
Window w2 = new Window(2);
void f()
{
System.out.println("f()");
}
Window w3 = new Window(3);
}public class OrderOfInitialization { //这里换成static Window w = new Window(4);楼主试试
//Window w = new Window(4);
public static void main(String[] args) {
House h = new House();
h.f();
}}
Thread[Thread-0,5,main]
false
Initialization is finished!
(2)Thread[main,5,main]
Thread[Thread-0,5,main]
true
Initialization is finished!
没有差别的地方我就不说了,被标示的是有差别的地方,原因:
staitc是静态方法,也就是说程序已被创建就调用static,所以第一个程序你一创建InitPuzzle的对象,程序就自动先执行一遍static方法体中的方法,由于没有执行private static Thread t = new Thread(new Runnable() {
public void run() {
System.out.println(Thread.currentThread());
initialized = true;
}
});
所以当执行t.start()方法时,参数还是false;
当你去掉static时“{}”在java中叫做实例初始化块(instance initializer block),是除了static之外第二优先级的方法体,所以这时你调用t.start()时程序已经先执行static方法的run方法将参数变成true了,注意:此处“{}”不能去掉,否则就产生编译错误,另外我给出的运行结果不一定是虚拟机执行的顺序,因为当第一种情况是虚拟机是先执行打印false,在执行打印Thread[main,5,main] Thread[Thread-0,5,main] Initialization is finished!(这个是根据不同机器的运行效率决定的,你可以再你的机器上实验下,此处涉及线程)
public void run() {
System.out.println("before");
initialized = true;
System.out.println("after");
}
});
你将t的定义改成如上所示,就会发现在打印false之前一定会打印出before,这就说明你说的“不过是后执行的”是错误的。
还有“然后在对函数初始化”,java里面没有“函数初始化”这个概念。
2 静态修饰的变量,是指该变量被所有的该类的对象共享。其存储的位置是在 内存的方法区。
注意 静态变量在类加载的时候初始化的
Thread[main,5,main]
false
Initialization is finished!
after
(2)before
after
Thread[main,5,main]
true
Initialization is finished!
这是你改了之后的结果,如果像你说的那after的打印顺序你怎么解释,java的结果输出顺序不能只看代码的书写顺序,特别是线程这个地方,如果你想凭着人脑就分析虚拟机那是痴心妄想,这个地方不同机器的运行结果是不一样的。后面我说函数初始化实际上就是指类初始化函数
你还是没有正面回答我的问题呢,我问的是既然
System.out.println("before");
被执行到了,那么initialized = true;
为什么没有被执行呢?别跟我说什么线程执行顺序不可控制,你别忘记了static代码块中有Thread.sleep(1000); 1秒钟对于jvm来说是很长的一段时间了,主线程sleep了1秒钟足够t线程跑完了。如果你觉得1秒不够,你可以改成主线程休眠10秒,1分钟,看看结果如何呢?
new InitPuzzle1();
}
}
class InitPuzzle1{
private static boolean initialized = false;
private static Thread t = new Thread(new Runnable() {
public void run() {
initialized = true;
System.out.println("before");
System.out.println("after");
}
});
static{
t.start();
System.out.println(Thread.currentThread()); try{
t.sleep(5000);
System.out.println(initialized);
}catch (InterruptedException e){
throw new AssertionError(e);
}
} public InitPuzzle1(){
System.out.println("Initialization is finished!");
}
}你可以看看上面的输出结果,是不是更没有顺序
Thread[main,5,main]
false
Initialization is finished!
before
after
而且改变也是 相当于 加锁一样处于 同步状态
由于是Thread
所以在 t.start()之后不一定立刻执行t.run();执行顺序:
static {
1 ======= t.start();
2 ========System.out.println(Thread.currentThread());try{
3==========Thread.sleep(1000);
4==========System.out.println(initialized);
}catch (InterruptedException e){
throw new AssertionError(e);
}
}public void run() {
5 =========System.out.println(Thread.currentThread());
6 ==========initialized = true;
}
所以是和执行顺序有关的。你也可以试一下下面代码:private static Thread t = new Thread(new Runnable() {
public void run() {
System.out.println(Thread.currentThread());
initialized = true;
System.out.println("Thread -- t : " + InitPuzzle.initialized);
t_2.start();
}
}
);
private static Thread t_2 = new Thread(new Runnable() {
public void run() {
System.out.println(Thread.currentThread()); System.out.println("Thread t2: " + InitPuzzle.initialized);
}
}
);
t_2中的System.println中的InitPuzzle.initialized值为true;
"所以在 t.start()之后不一定立刻执行t.run();" 这没有问题,可是你别忘记了static代码块中有Thread.sleep(1000); 1秒钟对于jvm来说是很长的一段时间了,主线程sleep了1秒钟足够t线程跑完了。如果你觉得1秒不够,你可以改成主线程休眠10秒,1分钟,看看结果如何呢?
完毕。并且从结果来看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的时间,结果不受影响。
只是为什么被“阻塞”我也不能解释。
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();
}
}怀疑是不是static块对static变量是同步的?
不是。而且没有“static块对static变量”这种提法
static的叫类初始化块,构造对象那叫实例初始化。你搞混了
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,但是运行输出结果为什么不一样呢?
对我有用[0] 丢个板砖[0] 引用 举报 管理 TOP 回复次数:48
sunboylg
(sunboylg) 等 级:
#1楼 得分:0回复于:2010-03-25 17:17:11static 是静态的意思,也就是说它修饰的值是改变不了的,下面的第二个类里修饰属性时候没有用static,所以它的值是可以改变的!