java 类中的静态域的初始化和静态代码块的执行只在类加载的时候执行且只执行一次。
仅执行一次,所以这一定是线程安全的,由此引出的在单例设计模式中采用静态内部类中的静态域存储唯一一个实例,既保证了线程安全又保证了懒加载,此技术被称作(initialization on demand holder)。但不在本文讨论范围。
本文旨在验证静态代码块只执行一次,即线程安全。
我需要设计一个类,静态代码块需要执行较长时间,然后在测试方法中以多线程的方式触发此类的加载,然后检验结果,验证线程安全。
本人才疏学浅,如有错误请不吝赐教。
另外请尊重别人的劳动成果,如需转载请注明出处:
http://waitingkkk-163-com.iteye.com/blog/2231416
需要“较长时间加载”的类:
public class SlowInit { static{ System.out.println(Thread.currentThread().getName() + " class SlowInit begin to init static block"); try{ TimeUnit.SECONDS.sleep(5); }catch(Exception e){ e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + " class SlowInit static block init over"); } public static void say(){ System.out.println(Thread.currentThread().getName() + " say: hi~" ); }; }
测试类:
public class ConcurrencyTest { private static CountDownLatch startGate = new CountDownLatch(1); public static void main(String args[]){ for(int i=0; i<100; i++){ new Thread(task).start(); } startGate.countDown(); } private static Runnable task = new Runnable() { @Override public void run() { try { startGate.await(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } SlowInit.say(); } }; }
测试类中采用CountDownLatch技术模拟100个线程同时启动,然后都会触发SlowInit类的类加载。
测试结果如下:
Thread-33 class SlowInit begin to init static block Thread-33 class SlowInit static block init over Thread-33 say: hi~ Thread-96 say: hi~ Thread-91 say: hi~ Thread-87 say: hi~ Thread-97 say: hi~ Thread-77 say: hi~ Thread-1 say: hi~ …… …… ……
可以发现,只有一个线程可以触发类的加载过程,且在此类加载过程中,其他线程处于阻塞状态, 等待类加载的完成。
即:
java 静态代码块只在类加载时执行一次