Java開發中常用到單例模式,如Runtime就是用到的單例模式。常用的單例模式主要有以下幾種:
- 餓漢式單例
- 懶漢式單例
- final修飾的單例
- 保證線程安全的單例
- 枚舉型單例
餓漢式單例:也就是無論用不用實例,都會去創建實例
class Single{
//1、私有構造方法,使外部不能創建實例
private Single(){
}
//2、私有成員變量,外部不能修改
private static Single s=new Single();
//3、提供公共的方法,使外部得到一個實例
public static Single GetInstance(){
return s;
}
懶漢式單例:需要對象時才創建,也是單例的延遲加載模式
class Single{
//1、私有構造方法,使外部不能創建實例
private Single(){
}
//2、私有成員變量,外部不能修改
private static Single s;
//3、提供公共的方法,使外部得到一個實例
public static Single GetInstance(){
if(s==null){
s=new Single();
}
return s;
}
}
final型單例:用final變量修飾
class Single{
public static final Single s=new Single();
}
以上三種單例模式都是線程不安全的,當在多線程下就會出現多個單例的情況,也就是每個線程創建一個單例。在併發編程中,要保證線程安全,多以出現了以下兩種線程安全的模式:
volatile及synchronized修飾的單例:
class Singleton_1{
//volatile保證有序可見性、有序性,但是不保證原子性,可以禁止指令重排序
private volatile Singleton_1 singleton;
private Singleton_1(){}
public Singleton_1 getInstance(){
if(singleton==null){
//synchronized保證原子性
synchronized (Singleton.class){
//防止多個線程同時執行第一個判斷語句時,會創建多個實例
if(singleton==null){
singleton=new Singleton_1();
}
}
}
return singleton;
}
}
枚舉型單例:
/**
* 枚舉單例
* JVM會保證Enum不能被反射,並且構造器只執行一次
*/
class EnumSingleton{
private EnumSingleton(){}
public static EnumSingleton getInstance(){
return Singleton.SINGLETON.getInstance();
}
/**
* 此枚舉類默認繼承Enum而不是Object
* 枚舉類的構造器只能是私有的
*/
private enum Singleton{
/**
* 枚舉類的關鍵字
* 自動添加public static final修飾
*/
SINGLETON;
private EnumSingleton enumSingleton;
//JVM保證此方法絕對只調用一次
private Singleton(){
enumSingleton=new EnumSingleton();
}
public EnumSingleton getInstance(){
return enumSingleton;
}
}
}