JAVA 與 MyCat(2) 單例模式
阿新 • • 發佈:2019-01-03
通過mycat來學習java了^^。
接前一篇:http://blog.csdn.net/john_chang11/article/details/78668667
MycatServer server = MycatServer.getInstance();
獲取MyCat例項,其實就是讀取配置檔案,並驗證正確性等。
MyCat例項必須全域性唯一,所以這裡涉及到JAVA的單例項模式,就是一個類只有唯一一個例項物件存在。先來看看mycat原始碼是怎麼做的:
public class MycatServer { private static final MycatServer INSTANCE = new MycatServer(); public static final MycatServer getInstance() { return INSTANCE; } private MycatServer() { ...... } }
首先,將構造方法定義成私有的,這樣外界不能再例項化該類。然後,提供一個公有的靜態方法,使外界只能通過該方法來獲取類例項,該方法返回一個型別為類本身的靜態屬性值,該屬性值在類載入時呼叫私有構造方法初始化。這就保障了,該類只有唯一一個例項物件的存在。
上面這種寫法是單例項建立的餓漢模式,執行緒安全,但浪費記憶體空間,不過mycat要執行MycatServer類是肯定要裝載的,所以原始碼裡這樣用也沒有問題。單例項模式的寫法還有別的寫法,一起看看。
1.懶漢,省記憶體空間,但執行緒不安全,不推薦使用
public class Singleton { private static Singleton instance=null; private Singleton(){ } public static Singleton getInstance(){ if(instance==null){ instance=new Singleton(); } return instance; } }
使用時才初始化例項,所以省記憶體,但也影響了速度,而且執行緒不安全,只能在單執行緒環境下可行,不推薦使用。
2.懶漢,執行緒安全,但效率低,不推薦使用
這種方式也是在使用時才初始化,省記憶體,但每次呼叫getInstance()方法時,都需要獲取同步鎖,非常耗時,也不推薦使用。public class Singleton { private static Singleton instance=null; private Singleton(){ } public static synchronized Singleton getInstance(){ if(instance==null){ instance=new Singleton(); } return instance; } }
3.懶漢,雙重檢查鎖,依然有問題,不推薦使用
public class Singleton {
private static Singleton instance=null;
private Singleton(){
}
public static Singleton getInstance(){
if(instance==null){
synchronized(Singleton.class){
if(instance==null){
instance=new Singleton();
}
}
}
return instance;
}
}
4.餓漢,執行緒安全,效率高,但記憶體使用率低,推薦使用
public class Singleton {
private static Singleton instance=new Singleton();
private Singleton(){
}
public static Singleton getInstance(){
return instance;
}
}
這種方式,是利用JVM的機制:靜態例項的初始化是ClassLoader經由[ThreadSafe]來完成,所以是執行緒安全的。該方法去除的同步,且類載入時就建立例項,所以效率高。但由於是類載入時就建立例項,所以記憶體使用率低,不過既然使用該類一般就會初始化該類的一個例項,所以該仍然推薦使用。
5.靜態內部類,集所有優點於一身,推薦使用
public class Singleton {
private Singleton(){
}
private static class SingletonHolder{
private final static Singleton instance=new Singleton();
}
public static Singleton getInstance(){
return SingletonHolder.instance;
}
}
內部類不會隨主類載入而載入,只有在第一次使用時才會載入,而單例項又是內部類的靜態例項,所以用這種方式獲取單例項,即是lazy loading,節省記憶體,又是執行緒安全且不需要同步鎖的。所以用這種方式獲取單例項最好。不過,使用時才建立例項,會對第一次呼叫產生影響,所以這種方式與第4種方式,可以互補使用:如果單例項類一定需要初始化,就用第4種,如果不一定需要初始化,就用第5種。