懒汉式
public class SingletonLazy {
private static SingletonLazy instance;
//初始化一个实例
private SingletonLazy() {};
//私有化该类的构造器
public static SingletonLazy getInstance() {//对外提供共有的访问方式,访问此实例对象
if (instance==null) {
instance = new SingletonLazy();
}
//如果没有实例,就创建一个
return instance;
//返回实例对象
}
}
饿汉式
public class SingletonHungary {
private static final SingletonHungary instance=new SingletonHungary();
//创建一个静态的不可变的私有实例对象
private SingletonHungary() {}
//私有化该类的构造器
public static SingletonHungary getInstance() {
return instance;
}
}
双重锁机制DCL
public class SingletonDoubleChecking {
private static SingletonDoubleChecking instance;//初始化一个实例
private SingletonDoubleChecking() {}//私有化构造器
public static SingletonDoubleChecking getInstance() {//对外提供共有的访问该实例的方法
if (instance==null) {//检查是否为空,不为空时不检查,节省性能消耗;为空时可能有并发问题
synchronized (SingletonDoubleChecking.class) {
if (instance==null) {
instance =new SingletonDoubleChecking();
}
}
}
return instance;
}
}
枚举
/**
- 枚举式单例,枚举的创建由JVM保证,因此不会出现并发问题,构造器自动私有,外部不能创建,只能引用
- 用法为:SingletonEnum.INSTANCE.doSomething();
*/
public enum SingletonEnum {
//唯一实例,默认为public static final的
INSTANCE;
public String name;
public void doSomething(){
System.out.println(“doSomething”);
}
public static void main(String[] args) {
SingletonEnum.INSTANCE.doSomething();
}
}
四种表现形式的区别
饿汉式跟懒汉式的话他们两个都是线程不安全的,饿汉式是在类加载的时候就创建实例对象,而懒汉式是当需要用到该实例的时候他才去创建一个实例,开发当中一般用的饿汉式。
另外就要说到双重锁机制DCL了,它是线程安全的,当遇到并发的时候,它能很好的起作用,先判断实例为不为NULL,不为空则不用管,直接返回该实例就行了,当它为NULL时,就用synchronized为它加锁,再次判断是否为空,为空就创建实例,不为空就返回实例。
枚举在例子中有介绍
他们四种方式共有的操作步骤就是:先私有化一个实例对象,再私有化该类的构造器,然后对外提供共有的访问方式来访问该实例对象,细微的差别就是创建实例的时间。