package example; class Demo{ static { //创建匿名内部类来启动新线程 Thread t = new Thread() { public void run() { System.out.println("进入run方法"); System.out.println("------" + website); website = "www.leegang.org"; System.out.println("++++++" + website); System.out.println("退出run方法"); } }; t.start(); try { //加入t线程 t.join(); } catch (InterruptedException e) { e.printStackTrace(); } } //定义一个静态field static String website = "www.crazyit.org"; public static void main(String args[]) { System.out.println("main:" + Demo.website); } }
奇怪的是只输出了进入run方法,并且在等待停止。
分析:
1,main线程试图访问Demo.website值,此时website尚未被初始化,因此main线程开始对该类执行初始化,步骤
(1)为该类所有静态field分配内存
(2)调用静态初始化块的代码执行初始化
2,main线程为Demo类的website field分配内存空间,值为null
3,main线程执行静态初始化块,创建一个新线程,并调用了join()方法,这说明main线程必须要等待新线程结束才能运行。
4,新线程打印"进入run方法",并试图运行System.out.println("------" + website);这时用到了website,但website正在main线程中初始化,
因为新线程会等待main线程对Demo类初始化结束。
5.两个线程 相互等待,形成死锁
下面去掉join()方法,查看结果
package example; class Demo{ static { //创建匿名内部类来启动新线程 Thread t = new Thread() { public void run() { System.out.println("进入run方法"); System.out.println("------" + website); website = "www.leegang.org"; System.out.println("++++++" + website); System.out.println("退出run方法"); } }; t.start(); /*try { //加入t线程 t.join(); } catch (InterruptedException e) { e.printStackTrace(); } */ } //定义一个静态field static String website = "www.crazyit.org"; public static void main(String args[]) { System.out.println("main:" + Demo.website); } }
main:www.crazyit.org
进入run方法
------www.crazyit.org
++++++www.leegang.org
退出run方法
此时,main线程不会等待新线程结束,接着往下初始化,static String website = "www.crazyit.org"; 并打印,
接着之后再去新线程代码。(调用一条线程的start方法后,该线程不会立即进入运行状态,只是保持在就绪状态)。
在调用新线程时,让主线程暂停一下。
package example; class Demo{ static { //创建匿名内部类来启动新线程 Thread t = new Thread() { public void run() { System.out.println("进入run方法"); System.out.println("------" + website); website = "www.leegang.org"; System.out.println("++++++" + website); System.out.println("退出run方法"); } }; t.start(); try { Thread.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } } //定义一个静态field static String website = "www.crazyit.org"; public static void main(String args[]) { System.out.println("main:" + Demo.website); } }
进入run方法
------www.crazyit.org
main:www.crazyit.org
++++++www.leegang.org
退出run方法
主线程暂停时,进行新线程执行代码,打印进入run方法之后, 执行System.out.println("------" + website);,
但由于还没有初始化完成,所以会切换会main线程进行初始化website后,再去执行新线程。
静态初始化启动的新线程赋值不是初始化操作,只是一次普通的赋直,如下代码编译失败。
package example; class Demo{ static { //创建匿名内部类来启动新线程 Thread t = new Thread() { public void run() { // website = "www.abc.org"; } }; t.start(); try { Thread.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } } //final static String website ; 编译失败 public static void main(String args[]) { } }