懒汉模式实现单例
public class singleMode {
private static singleMode sing = null;
private singleMode () {
/**
* 必须私有化构造方法,避免外部创建新对象
*/
}
public static singleMode getSing() {
/**
* 线程不安全,可能会多个线程进入if语句创建出新对象,解决方法加synchronized同步新建对象操作
*/
if (sing == null)
sing = new singleMode();
return sing;
}
}
懒汉模式实现单例加同步模块
class singleMode1 {
/**
* 懒汉模式实现单例加同步模块
*/
private static singleMode1 sing = null;
private singleMode1 () {
/**
* 必须私有化构造方法,避免外部创建新对象
*/
}
public static singleMode1 getSing() {
/**
* 此时解决了同步问题但是可能会导致对象溢出
* JVM在创建对象时会执行三个操作:
* 1.为对象分配空间
* 2.初始化对象
* 3.设置instance指向第一步创建的空间
* 但是JVM和CPU在实际创建对象时可能对上面的步骤进行重排序,使该步骤变成1,3,2
* 这就有可能使在一个线程还没有初始化对象时对象就已经不为null了,这时别的线程在调用getsing()函数时会直接返回一个还没有初始化好的对象
* 解决方法,使用volatile修饰该引用,禁止创建对象时重排序,保证每次调用的sing都是最新值
*/
if (sing == null)
synchronized (singleMode1.class) {
if (sing == null)
sing = new singleMode1();
}
return sing;
}
}
懒汉模式正确写法
class singleMode2 {
/**
* 懒汉模式正确写法
* 懒汉模式缺点,使用synchronized同步代码块,降低了多线程时的并发效率
*/
private volatile static singleMode2 sing = null; // 加volatile禁止创建对象时重排序
private singleMode2 () {
}
public static singleMode2 getSing() {
if (sing == null)
synchronized (singleMode1.class) { // 加双重验证同步代码块
if (sing == null)
sing = new singleMode2();
}
return sing;
}
}
饿汉模式
class singleMode3 {
/**
* 饿汉模式
* 缺点:在没有初始化单例时,占用不必要的内存
*/
private static singleMode3 sing = new singleMode3(); // 线程安全,无论创建多少对象,静态变量只会初始化一次
private singleMode3() {
}
// 静态的工厂方法
public static singleMode3 getSing() {
return sing;
}
}
枚举模式,最安全,推荐使用
class singleMode4 {
/**
* 枚举模式,最安全,推荐使用
*/
private singleMode4() {
}
public static singleMode4 getSing() {
return Singleton.INSTANCE.getSing();
}
private enum Singleton {
INSTANCE;
private singleMode4 sing;
// JVM保证次构造方法只会执行一次,且在getSing调用之前会被初始化
Singleton (){
sing = new singleMode4();
}
public singleMode4 getSing() {
return sing;
}
}
}