java学习笔记|单例模式

什么是单例 (这个我就感觉是一堆废话)

Singleton:在Java中即指单例设计模式,它是软件开发 中最常用的设计模式之一。

单例设计模式,即某个类在整个系统中只能有一个实例对象可被获取和使用的代码模式。

要点(算是概括的蛮好的,也算单例模式的特点)

  • 是某个类只能有一个实例
    即构造器私有化
  • 是它必须自行创建这个实例
    即含有一个该类的静态变量来保存这个唯一的实例
  • 是它必须自行向整个系统提供这个实例
    即对外提供获取该实例对象的方法
    (1)直接暴露 (2)用静态变量的get方法

几种常见模式

  • 饿汉式:直接创建对象,不存在线程安全问题
    直接实例化饿汉式(简洁直观)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
       /**
    * 饿汉式: 直接创建实例,不管你是否需要这个对象都会创建
    * (1)构造器私有化
    * (2)自行创建,并且用静态变量保存
    * (3)向外提供这个实例
    * (4)强调这是一个单例,我们可以用final修饰
    */
    public class Singleton_1 {
    public static final Singleton_1 INSTANCE = new Singleton_1() ;
    private Singleton_1(){
    }
    }

    枚举式(最简洁) JDK1.5以后有枚举类 (枚举类的构造器都是私有化)

    1
    2
    3
    4
    5
    6
    7
    /**
    * 枚举类型:表示该类型的对象是有限的几个
    * 我们可以限定为一个,就成了单例
    */
    public enum Singleton_2 {
    INSTANCE;
    }

    静态代码块饿汉式(适合复杂实例化)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    public class Singleton_3 {
    public static final Singleton_3 INSTANCE ;
    static {
    INSTANCE = new Singleton_3();
    }
    private Singleton_3(){

    }
    }
    #为什么饿汉式是线程安全的?(算是自己总结的)

    java设计的类加载器就可以避免线程安全的问题,在类初始化的时候就已经创建好实例对象,一个类在整个生命周期只会加载一次,也就是说每次线程只会拿到一个对象,所以说是线程安全的。

  • 懒汉式:延迟创建对象
    线程不安全(适用于单线程)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    /**
    * 懒汉式单例
    * (1)构造器私有化
    * (2)用一个静态变量保存这个唯一的实例
    * (3)提供一个静态方法,获取这个实例对象
    */
    public class Singleton_4 {
    private static Singleton_4 instance ;
    private Singleton_4(){

    }
    public static Singleton_4 getInstance(){
    if (instance==null){
    instance = new Singleton_4();
    }
    return instance;
    }
    }

    线程安全(适用于多线程)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    public class Singleton_4 {
    private static Singleton_4 instance ;
    private Singleton_4(){

    }
    public static Singleton_4 getInstance() {
    synchronized(Singleton_4.class){
    if (instance==null){
    instance = new Singleton_4();
    }
    }
    return instance;
    }
    }

    静态内部类形式(适用于多线程)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    /**
    * 在内部类被加载和初始化时,オ创建INSTANCE实例对象
    * 静态内部类不会自动随着外部类的加载和初始化而初始化,它是要单独去加载和初始化的。
    * 因为是在内部类加载和初始化创建的,所以是线程安全的
    */
    public class Singleton_5 {
    private Singleton_5(){

    }
    private static class Inner{
    private static final Singleton_5 INSTANCE = new Singleton_5();
    }
    public static Singleton_5 getInstance(){
    return Inner.INSTANCE;
    }
    }