1 /*** 2 * 1. 最简单的实现 3 * 4 * 5 */ 6 7 /* 8 public class SingletonClass { 9 private SingletonClass(){} 10 private static final SingletonClass instance=new SingletonClass(); 11 private static SingletonClass getInstance(){ 12 return instance; 13 } 14 15 } 16 */ 17 /** 18 * 19 * 2.性能优化 20 * 21 */ 22 /*public class SingletonClass{ 23 private SingletonClass(){} 24 private static SingletonClass instance=null; 25 public static SingletonClass getInstance(){ 26 if(instance==null){ 27 instance=new SingletonClass(); 28 } 29 return instance; 30 } 31 }*/ 32 /*** 33 * 34 * 3、同步,应对多线程 35 * 36 */ 37 /*public class SingletonClass{ 38 private SingletonClass() { 39 } 40 private static SingletonClass instance=null; 41 public synchronized static SingletonClass getInstance(){ 42 if(instance==null){ 43 instance=new SingletonClass(); 44 } 45 return instance; 46 47 } 48 } 49 */ 50 /*** 51 * 4.又是性能 52 */ 53 /*public class SingletonClass{ 54 private SingletonClass(){} 55 private static SingletonClass instance=null; 56 public static SingletonClass getInstance(){ 57 synchronized(SingletonClass.class){ 58 if(instance==null){ 59 instance=new SingletonClass(); 60 } 61 } 62 return instance; 63 } 64 } 65 */ 66 //double-checked locking设计 67 /*public class SingletonClass{ 68 private SingletonClass(){} 69 private static SingletonClass instance=null; 70 public SingletonClass getInstance(){ 71 if(instance==null){ 72 synchronized(SingletonClass.class){ 73 if(instance==null){ 74 instance=new SingletonClass(); 75 } 76 } 77 } 78 return instance; 79 } 80 }*/ 81 /*** 82 * 5. 从源头检查 83 */ 84 /** 85 * 86 * 创建一个变量需要哪些步骤呢?一个是申请一块内存,调用构造方法进行初始化操作,另一个是分配 87 * 一个指针指向这块内存。这两个操作谁在前谁在后呢?JVM规范并没有规定。那么就存在这么一种情况, 88 * JVM是先开辟出一块内存,然后把指针指向这块内存,最后调用构造方法进行初始化。下面我们来考虑 89 * 这么一种情况:线程A开始创建SingletonClass的实例,此时线程B调用了getInstance()方法,首先 90 * 判断instance是否为null。按照我们上面所说的内存模型,A已经把instance指向了那块内存,只是 91 * 还没有调用构造方法,因此B检测到instance不为null,于是直接把instance返回了——问题出现了, 92 * 尽管instance不为null,但它并没有构造完成,就像一套房子已经给了你钥匙,但你并不能住进去, 93 * 因为里面还没有收拾。此时,如果B在A将instance构造完成之前就是用了这个实例,程序就会出现错误了! 94 * 95 */ 96 /*public class SingletonClass{//wrong job 97 private SingletonClass(){} 98 private static SingletonClass instance=null; 99 public static SingletonClass getInstance(){ 100 if(instance==null){ 101 SingletonClass sc; 102 synchronized(SingletonClass.class){ 103 sc=instance; 104 if(sc==null){ 105 synchronized(SingletonClass.class){ 106 if(sc==null){ 107 sc=new SingletonClass(); 108 } 109 } 110 } 111 instance=sc; 112 } 113 114 } 115 return instance; 116 } 117 }*/ 118 119 /*** 120 * 121 * 6.解决方案 122 * 123 */ 124 //在JDK 5之后,Java使用了新的内存模型。volatile关键字有了明确的语义——在JDK1.5之前, 125 //volatile是个关键字,但是并没有明确的规定其用途——被volatile修饰的写变量不能和之前的读写代码调整, 126 //读变量不能和之后的读写代码调整!因此,只要我们简单的把instance加上volatile关键字就可以了。 127 /*public class SingletonClass{ 128 private SingletonClass(){} 129 private volatile static SingletonClass instance=null; 130 public static SingletonClass getInstance(){ 131 if(instance==null){ 132 synchronized(SingletonClass.class){ 133 if(instance==null){ 134 instance=new SingletonClass(); 135 } 136 } 137 } 138 return instance; 139 } 140 }*/ 141 /*** 142 * 推荐用法 143 */ 144 /*public class SingletonClass{ 145 private SingletonClass(){} 146 //Java的静态内部类 147 private static class SingletonClassInstance{ 148 private static final SingletonClass instance=new SingletonClass(); 149 } 150 public static SingletonClass getInstance(){ 151 return SingletonClassInstance.instance; 152 } 153 } 154 */
时间: 2024-10-29 19:09:48