标签:
单例设计模式几种实现 (测试所用jdk版本1.8.0_20)
第一种:
1 public final class SingleInstance1 { 2 3 private static volatile SingleInstance1 singleInstance = null; 4 /* 5 * 必须定义,防止jvm提供默认构造函数(默认的为public)这样就失去了单例的特性, 6 * 因为可以new一个实例 7 */ 8 private SingleInstance1(){} 9 public static SingleInstance1 getInstance(){ 10 if(singleInstance == null){ 11 synchronized (SingleInstance1.class) { 12 if(singleInstance == null){ 13 singleInstance = new SingleInstance1(); 14 } 15 } 16 } 17 return singleInstance; 18 } 19 }
这种模式是单锁,有线程安全问题 所以用两把锁
第二种:
1 /** 2 * 3 * 说明:线程安全的单例 4 * 5 */ 6 public final class SingleInstance2 { 7 8 private static volatile SingleInstance2 singleInstance = null; 9 10 /* 11 * 必须定义,防止jvm提供默认构造函数(默认的为public)这样就失去了单例的特性, 因为可以new一个实例 12 */ 13 private SingleInstance2() { 14 } 15 16 public static SingleInstance2 getInstance() { 17 if (singleInstance == null) { 18 synchronized (SingleInstance2.class){ 19 SingleInstance2 tmpInstance2 = singleInstance; 20 synchronized (SingleInstance2.class) { 21 if (tmpInstance2 == null) { 22 tmpInstance2 = new SingleInstance2(); 23 } 24 singleInstance = tmpInstance2; 25 } 26 } 27 } 28 return singleInstance; 29 } 30 }
第三种:
1 /** 2 * 3 * 说明:饿汉式 不是线程安全的 4 * 5 */ 6 public class SingleInstance3 { 7 private static SingleInstance3 singleInstance = null; 8 9 private SingleInstance3(){} 10 11 public SingleInstance3 getInstance3() { 12 if(singleInstance == null) { 13 singleInstance = new SingleInstance3(); 14 } 15 return singleInstance; 16 17 } 18 19 }
第四种:
1 /** 2 * 3 * 说明:懒汉式 缺点:每个对象在没有使用之前就已经初始化了。这就可能带来潜在的性能问题 4 * 没有使用这个对象之前,就把它加载到了内存中去是一种巨大的浪费 5 */ 6 public class SingleInstance4 { 7 private static SingleInstance4 singleInstance = new SingleInstance4(); 8 9 private SingleInstance4() { 10 } 11 12 public SingleInstance4 getInstance() { 13 return singleInstance; 14 } 15 16 }
第五种:
1 /** 2 * 3 *说明:线程安全 但是效率低,因为只需要创建时同步就可以了 不需要每次访问都要同步 4 */ 5 public class SingleInstance5 { 6 private static SingleInstance5 singleInstance5 = null; 7 private SingleInstance5() { 8 } 9 10 public static synchronized SingleInstance5 getInstance5(){ 11 if(singleInstance5 == null){ 12 singleInstance5 = new SingleInstance5(); 13 } 14 return singleInstance5; 15 } 16 }
第六种:
1 /** 2 * 3 *内部类静态属性(或静态块)会在内部类第一次被调用的时候按顺序被初始化(或执行)而且只会被加载一次 4 *测试请看StaticInnerClassLoaderTime类 5 */ 6 public class SingleInstance6 { 7 private SingleInstance6() {} 8 private static class SingletonHolder { 9 public final static SingleInstance6 instance = new SingleInstance6(); 10 } 11 12 public static SingleInstance6 getInstance() { 13 return SingletonHolder.instance; 14 } 15 16 }
StaticInnerClassLoaderTime类
1 public class StaticInnerClassLoaderTime { 2 3 public static class Inner { 4 static { 5 System.out.println("TestInner Static!"); 6 } 7 public final static StaticInnerClassLoaderTime testInstance = 8 new StaticInnerClassLoaderTime(3); 9 } 10 11 public static StaticInnerClassLoaderTime getInstance() { 12 return Inner.testInstance; 13 } 14 15 public StaticInnerClassLoaderTime(int i) { 16 System.out.println("Test " + i + " Construct! "); 17 } 18 19 20 // 类静态属性 21 public static StaticInnerClassLoaderTime testOut = 22 new StaticInnerClassLoaderTime(1); 23 24 public static int value = 3; 25 // 类静态块 26 static { 27 System.out.println("Test Static" + testOut); 28 } 29 30 public static void main(String args[]) { 31 StaticInnerClassLoaderTime t = new StaticInnerClassLoaderTime(2); 32 //说明静态内部类只有在调用时才会被加载 而且只会被加载一次 因此最好的单例设计模式是用静态内部类 33 StaticInnerClassLoaderTime.getInstance(); 34 StaticInnerClassLoaderTime.getInstance(); 35 } 36 37 }
运行结果:
1 Test 1 Construct! 2 Test Staticcn.canon.Single.StaticInnerClassLoaderTime@15db9742 3 Test 2 Construct! 4 TestInner Static! 5 Test 3 Construct!
说明:
顺序是:父类静态属性-》父类静态代码块-》子类静态变量-》子类静态代码块-》父类非静态变量-》父类非静态代码块-》父类构造函数-》
子类非静态变量-》子类非静态代码块-》-》子类构造函数
这样的加载顺序不是绝对的 因为静态变量和静态代码块跟声明顺序有关。
对于如果静态代码块中调用静态变量,那么静态变量必须在静态代码块前面声明;如果静态代码块中没有调用静态变量,
那么就跟顺序有关了,谁先声明谁先被加载。说白了还是顺序加载,之所以会出现“如果静态代码块中调用静态变量,
那么静态变量必须在静态代码块前面声明”,是因为变量是声明,所以出现编译错误。
应用到内部类中 静态变量和静态代码块跟声明顺序有关。 这样就可以解释你的问题了。内部类也是类。
类静态块-类静态属性这个跟顺序有关系 如果类静态属性在类静态代码块之前 那么类静态属性先初始化
标签:
原文地址:http://www.cnblogs.com/yang--yang/p/4856957.html