java23种设计模式+单例_Java23种设计模式之单例模式
一、單例模式簡介
單例模式是Java設計模式中常見的一種模式。主要分為懶漢式單例、餓漢式單例、登記式單例;
單例模式的特點: ?1、單例類只能有一個實例; ?2、單例類必須自己創建自己的唯一的實例; 3、單例類必須給所有其他對象提供這一實例;
二、餓漢式單例
public classSingleTonModel {privateSingleTonModel(){}private static final SingleTonModel singt=newSingleTonModel();public staticSingleTonModel getInstance(){returnsingt;
}
}
餓漢式在類創建的同時就已經創建好一個靜態的對象供系統使用,以后不再改變,所以天生是線程安全的。
三、懶漢式單例
簡單的例子:
public classSingleTonModel {privateSingleTonModel(){}private static SingleTonModel singt=null;public staticSingleTonModel getInstance(){if(singt==null){
singt=newSingleTonModel();
}returnsingt;
}
}
Singleton通過將構造方法限定為private避免了類在外部被實例化,在同一個虛擬機范圍內,Singleton的唯一實例只能通過getInstance()方法訪問。
(事實上,通過Java反射機制是能夠實例化構造方法為private的類的,那基本上會使所有的Java單例實現失效。此問題在此處不做討論,姑且掩耳盜鈴地認為反射機制不存在。)
但是以上懶漢式單例的實現沒有考慮線程安全問題,它是線程不安全的,并發環境下很可能出現多個Singleton實例,要實現線程安全,有以下三種方式,都是對getInstance這個方法改造,保證了懶漢式單例的線程安全:(課外知識可以了解線程安全)
改造一:在靜態方法上添加關鍵詞:synchronized,進行同步
public classSingleTonModel {privateSingleTonModel(){}private static SingleTonModel singt=null;public staticsynchronizedSingleTonModel getInstance(){if(singt==null){
singt=newSingleTonModel();
}returnsingt;
}
}
雖然通過同步保障了線程安全,但是每次都要同步,會影響性能,畢竟99%的情況下是不需要同步的。
改造二:在判斷不存在實例時才進行同步
public classSingleTonModel {privateSingleTonModel(){}private static SingleTonModel singt=null;public staticSingleTonModel getInstance(){if(singt==null){
synchronized(SingleTonModel.class){if(singt==null){
singt=newSingleTonModel();
}
}
}returnsingt;
}
}
在getInstance中做了兩次null檢查,確保了只有第一次調用單例的時候才會做同步,這樣也是線程安全的,同時避免了每次都同步的性能損耗。
改造三:添加內部靜態類
public classSingleTonModel {privateSingleTonModel(){}private static classlanSingleton{private static final SingleTonModel singt=newSingleTonModel();
}public staticfinal SingleTonModel getInstance(){returnlanSingleton.singt;
}
}
利用了classloader的機制來保證初始化instance時只有一個線程,所以也是線程安全的,同時沒有性能損耗,所以一般我傾向于使用這一種。
四、登記式單例(很少用)
/類似Spring里面的方法,將類名注冊,下次從里面直接獲取。public classSingleton3 {private static Map map = new HashMap();static{
Singleton3 single= newSingleton3();
map.put(single.getClass().getName(), single);
}//保護的默認構造子
protectedSingleton3(){}//靜態工廠方法,返還此類惟一的實例
public staticSingleton3 getInstance(String name) {if(name == null) {
name= Singleton3.class.getName();
System.out.println("name == null"+"--->name="+name);
}if(map.get(name) == null) {try{
map.put(name, (Singleton3) Class.forName(name).newInstance());
}catch(InstantiationException e) {
e.printStackTrace();
}catch(IllegalAccessException e) {
e.printStackTrace();
}catch(ClassNotFoundException e) {
e.printStackTrace();
}
}return map.get(name);
}//一個示意性的商業方法
publicString about() {return "Hello, I am RegSingleton.";
}public static voidmain(String[] args) {
Singleton3 single3= Singleton3.getInstance(null);
System.out.println(single3.about());
}
}
登記式單例實際上維護了一組單例類的實例,將這些實例存放在一個Map(登記薄)中,對于已經登記過的實例,則從Map直接返回,對于沒有登記的,則先登記,然后返回。
課外小知識:
1、什么是線程安全
如果你的代碼所在的進程中有多個線程在同時運行,而這些線程可能會同時運行這段代碼。如果每次運行結果和單線程運行的結果是一樣的,而且其他的變量的值也和預期的是一樣的,就是線程安全的。
或者說:一個類或者程序所提供的接口對于線程來說是原子操作,或者多個線程之間的切換不會導致該接口的執行結果存在二義性,也就是說我們不用考慮同步的問題,那就是線程安全的。
總結
以上是生活随笔為你收集整理的java23种设计模式+单例_Java23种设计模式之单例模式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java怎么添加地图_javaweb怎样
- 下一篇: java 发送cookie_Java如何