设计模式之单例模式

回顾概念:
Java中单例模式是一种常见的设计模式,单例模式的写法有好几种,我在这里主要介绍两种:懒汉式单例和饿汉式单例。
  单例模式有以下特点:
  1、单例类只能有一个实例。
  2、单例类必须自己创建自己的唯一实例。
  3、单例类必须给所有其他对象提供这一实例。
  单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。在计算机系统中,线程池、缓存、日志对象、对话框、打印机、显卡的驱动程序对象常被设计成单例。
一、懒汉模式
懒汉模式:类加载器在加载类的时候,不会创建实例,只有当需要创建对象的时候,才会去创建类的实例。
1、最简单的,但不是线程安全的懒汉模式。

public class Singleton {
    //私有化构造方法,防止外部使用new来创建对象。
    private Singleton () {}
    private static Singleton single = null;
    public static Singleton getInstance () {
        if(single == null) {
            single = new Singleton();
        }
        return single;
    }
}

2、线程安全的懒汉模式,但是实际运行中效果很差,类似数据库中的表锁。

public class Singleton {
    //私有化构造方法,防止外部使用new来创建对象。
    private Singleton () {}
    private static Singleton single = null;
    public static synchronized Singleton getInstance () {
        if(single == null) {
            single = new Singleton();
        }
        return single;
    }
}

3、双重校验锁,类似数据库中的行锁

public class Singleton {
    //私有化构造方法,防止外部使用new来创建对象。
    private Singleton () {}
    //volatile关键字用于线程可见
    private static volatile Singleton single = null;
    public static Singleton getInstance () {
        if(single == null) {
            //锁住类对象
            synchronized(Singleton.Class) {
                if(single == null) {
                    single = new Singleton();
                }
            }
        return single;
        }
    }
}

4、静态内部类方法

public class Singleton {
    //私有化构造方法,防止外部使用new来创建对象。
    private Singleton () {}
    private static class LazyHolder {  
        //被final修饰的实例变量是无法被修改的,这就保证的对象的唯一性
       private static final Singleton single = new Singleton();  
    }  
    public static Singleton getInstance() {  
       return LazyHolder.single;  
    } 
}

二、饿汉模式
饿汉模式:类加载器加载的过程中,就已经创建好实例,因为是在类加载初始阶段就已经加载好了实例,所以饿汉模式总是线程安全的。
5、最简单的,

public class Singleton {
    //私有化构造方法,防止外部使用new来创建对象。
    private Singleton () {}
    //被final修饰的实例变量是无法被修改的,这就保证的对象的唯一性
    private static final Singleton single =new Singleton();
    public static synchronized Singleton getInstance () {
        return single;
    }
}

6、与5同理,但是代码实现方式不同

public class Singleton {
    //私有化构造方法,防止外部使用new来创建对象。
    private Singleton () {}
    //被final修饰的实例变量是无法被修改的,这就保证的对象的唯一性
    private static final Singleton single = null;
    //被static修饰的静态代码块会在类加载期间,类加载器直接运行。
    static {
        single = new Singleton();
    }
    public static synchronized Singleton getInstance () {
        return single;
    }
}

总结:建议在选择单例模式的时候选择用双重校验锁或静态内部类的方式,这两种方式能够实现并发效率最优,但是当你确定某个类一定会被创建实例时,饿汉也是不错的选择。

参考博客:
JAVA设计模式之单例模式

原文地址:https://www.cnblogs.com/loren-Yang/p/7466133.html