Java 設計模式之單例模式
單例模式的三種實現方式
- 餓漢式
餓漢式顧銘思議是在類加載時便生成對象,由於在類加載的時候就生成了對象,餓漢式是線程安全的,但是會造成空間的浪費。
package com.lin.lon;
public class SingletonForHungry {
public static SingletonForHungry singleton= new SingletonForHungry();
private SingletonForHungry(){
}
public static SingletonForHungry getInstance(){
return singleton;
}
}
2.懶漢式
懶漢式相對於餓漢式而言,只有在方法被調用的時纔會創建對象,由於懶漢式是動態的調用,因此會存在線程安全問題。
- 第一種實現方式,該實現方式會造成線程安全問題
package com.lin.lon;
public class SingletonForLangOne {
private static SingletonForLangOne singletonForLang;
private SingletonForLangOne(){
}
public static SingletonForLangOne getInstance(){
if (singletonForLang == null){
return new SingletonForLangOne();
}else {
return singletonForLang;
}
}
}
- 第二種實現方式,該方式能夠避免線程安全問題,但會影響性能,一般有兩種寫法,推薦第二種寫法,第一種寫法消耗的性能過大
package com.lin.lon;
public class SingletonForLangTwo {
private static SingletonForLangTwo singletonForLang;
private SingletonForLangTwo(){
}
public static synchronized SingletonForLangTwo getInstance(){
if (singletonForLang == null){
return new SingletonForLangTwo();
}else {
return singletonForLang;
}
}
}
package com.gupaoedu.singleton;
public class Singleton3 {
private Singleton3() {}
private static Singleton3 single=null;
public static Singleton3 getInstance() {
if (single == null) {
synchronized (Singleton3.class) {
if (single == null) {
single = new Singleton3();
}
}
}
return single;
}
}
- 第三種實現方式,該方式能夠很好的兼顧懶漢式的動態與線程安全問題造成的性能損失
package com.lin.lon;
public class SingletonForLangThree {
private static class InnerForSingle{
private static final SingletonForLangThree singletonForLang = new SingletonForLangThree();
}
private SingletonForLangThree(){
}
public static synchronized SingletonForLangThree getInstance(){
return InnerForSingle.singletonForLang;
}
}
3.註冊式
Spring中即採用此種方式,註冊時是在啓動時將類名和類註冊到Map中,當需要使用時傳遞給方法所需要使用的類名即可獲得該對象
package com.lin.lon;
import java.util.HashMap;
import java.util.Map;
public class SingletonForRegister {
private static Map<String,SingletonForRegister> objectMap = new HashMap<>();
private SingletonForRegister(){
}
//類加載時將對象注入Map
static {
SingletonForRegister singleton = new SingletonForRegister();
objectMap.put("com.lin.lon.SingletonForRegister",singleton);
}
//該處可能會存在線程安全問題,博主目前還沒有更好的實現方式,不影響性能
public static SingletonForRegister getInstance(String className){
if (className == null){
className = SingletonForRegister.class.getName();
}
if (objectMap.get(className) ==null){
try {
objectMap.put(className, (SingletonForRegister) Class.forName(className).newInstance());
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
return objectMap.get(className);
}
}