4-1.单例模式

单例模式创建的8种写法:

 1.饿汉式(静态常量)

  2.饿汉式(静态代码块)

  3.懒汉式(新城不安全)

  4.懒汉式(线程安全,同步方法)

  5.懒汉式(线程安全,同步代码块)

  6.双重检索 

  7.静态内部类

  8.枚举

1.饿汉式(静态常量)

  步骤:

  1.构造器私有化(防止new对象)

  2.类的内部创建对象

  3.向外暴露一个静态的公共方法

public class SingleTest1 {
    public static void main(String[] args) {
        Singleton singleton1 = Singleton.getInstance();
        Singleton singleton2 = Singleton.getInstance();
        System.out.println(singleton1 == singleton2);
    }
}

class Singleton {
    //1.构造器私有化,防止外部new
    private Singleton() {
    }

    //2.本类中直接创建出实例
    private final static Singleton instance = new Singleton();

    //3.提供共有的方法获取该单例对象
    public static Singleton getInstance() {
        return instance;
    }
}

2.饿汉式(静态代码块)

public class SingleTest1 {
    public static void main(String[] args) {
        Singleton singleton1 = Singleton.getInstance();
        Singleton singleton2 = Singleton.getInstance();
        System.out.println(singleton1 == singleton2);
    }
}

class Singleton {
    //1.构造器私有化,防止外部new
    private Singleton() {
    }

    private final static Singleton instance;

    //2.静态代码块创建出实例
    static {
        instance = new Singleton();
    }

    //3.提供共有的方法获取该单例对象
    public static Singleton getInstance() {
        return instance;
    }
}

3.懒汉式(线程不安全)

public class SingleTest1 {
    public static void main(String[] args) {
        Singleton singleton1 = Singleton.getInstance();
        Singleton singleton2 = Singleton.getInstance();
        System.out.println(singleton1 == singleton2);
    }
}

class Singleton {
    //1.构造器私有化,防止外部new
    private Singleton() {
    }

    private static Singleton instance;

    //3.提供共有的方法获取该单例对象
    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

4.懒汉式(线程安全,同步方法)

public class SingleTest1 {
    public static void main(String[] args) {
        Singleton singleton1 = Singleton.getInstance();
        Singleton singleton2 = Singleton.getInstance();
        System.out.println(singleton1 == singleton2);
    }
}

class Singleton {
    //1.构造器私有化,防止外部new
    private Singleton() {
    }

    private static Singleton instance;

    //3.提供共有的方法获取该单例对象
    //加锁解决线程安全问题
    public static synchronized Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

5.懒汉式(有问题,不能写)

class Singleton {
    //1.构造器私有化,防止外部new
    private Singleton() {
    }

    private static Singleton instance;

    //3.提供共有的方法获取该单例对象
    public static  Singleton getInstance() {
        if (instance == null) {
            //当a线程拿到锁,b线程刚执行到这里时阻塞,a线程执行完毕,b线程不会再次判断而会直接进入到加锁代码块中,无法保证单例
            synchronized (Singleton.class){
                instance = new Singleton();
            }
        }
        return instance;
    }
}

 

6.双重检查(DCL)

class Singleton {
    //1.构造器私有化,防止外部new
    private Singleton() {
    }
    //2.加volatile保证线程可见性,禁止指令重排问题
    private static volatile Singleton instance;

    //3.提供共有的方法获取该单例对象
    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                //再加一次判断,解决上个例子的判断问题
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

 

7.静态内部类

class Singleton {
    private Singleton() {
    }
    //1.定义一个静态内部类
    //注意: 
    //1.当Singleton被装载时,静态内部类SingletonInstance是不会被装载的,因为jvm是按需加载
    //2.当调用getInstance方法时,类加载器会加载SingletonInstance的内部类,而且只加载一遍,是线程安全的
    //从而达到懒加载并且线程安全问题!
    private static class SingletonInstance {
        private static final Singleton INSTANCE = new Singleton();
    }

    public static Singleton getInstance() {
        return SingletonInstance.INSTANCE;
    }
}

8.枚举

public class SingleTest1 {
    public static void main(String[] args) {
        Singleton singleton1 = Singleton.INSTANCE;
        Singleton singleton2 = Singleton.INSTANCE;
        System.out.println(singleton1 == singleton2);
    }
}
enum Singleton{
    INSTANCE;
}


单例模式在JDK应用的源码分析

1.我们jdk中,java.lang.Runtime就是经典的单例模式:饿汉式

public class Runtime {
    private static Runtime currentRuntime = new Runtime();

    /**
     * Returns the runtime object associated with the current Java application.
     * Most of the methods of class <code>Runtime</code> are instance
     * methods and must be invoked with respect to the current runtime object.
     *
     * @return  the <code>Runtime</code> object associated with the current
     *          Java application.
     */
    public static Runtime getRuntime() {
        return currentRuntime;
    }

    /** Don't let anyone else instantiate this class */
    private Runtime() {}
    ...
    }

posted @ 2022-07-21 21:58  努力的达子  阅读(16)  评论(0编辑  收藏  举报