ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

单例模式

2020-05-15 13:06:57  阅读:205  来源: 互联网

标签:getInstance 模式 public instance static 单例 class


饿汉式(静态常量):

/**
 * 饿汉式(静态常量)
 *
 * 1.构造器私有
 * 2.定义一个静态常量保存一个唯一的实例对象(单例)
 * 3.提供一个静态方法返回单例对象
 */
public class Singleton01 {

    public static final Singleton01 INSTANCE = new Singleton01();

    private Singleton01() {}

    public static Singleton01 getInstance() {
        return INSTANCE;
    }

}

class Test01 {
    public static void main(String[] args) {
        Singleton01 s1 = Singleton01.getInstance();
        Singleton01 s2 = Singleton01.getInstance();
        System.out.println(s1 == s2); // true
    }
}

饿汉式(静态代码块):

/**
 * 饿汉式(静态代码块)
 *
 * 1.构造器私有
 * 2.定义一个静态常量保存一个唯一的实例对象(单例),通过静态代码块初始化单例对象
 * 3.提供一个静态方法返回单例对象
 */
public class Singleton02 {

    public static final Singleton02 INSTANCE;

    static {
        INSTANCE = new Singleton02();
    }

    private Singleton02() {}

    public static Singleton02 getInstance() {
        return INSTANCE;
    }

}

class Test02 {
    public static void main(String[] args) {
        Singleton02 s1 = Singleton02.getInstance();
        Singleton02 s2 = Singleton02.getInstance();
        System.out.println(s1 == s2); // true
    }
}

懒汉式(线程不安全,不推荐这样写):

/**
 * 懒汉式(线程不安全,不推荐这样写)
 *
 * 1.构造器私有
 * 2.定义一个静态变量存储一个单例对象(定义时不初始化该对象)
 * 3.提供一个静态方法返回单例对象,返回前先询问是否有,有则直接返回,没有则创建新的返回
 */
public class Singleton03 {

    public static Singleton03 instance;

    private Singleton03() {}

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

}

class Test03 {
    public static void main(String[] args) {
        Singleton03 s1 = Singleton03.getInstance();
        Singleton03 s2 = Singleton03.getInstance();
        System.out.println(s1 == s2); // true / false
    }
}

懒汉式(线程安全,性能差,不推荐这样写):

/**
 * 懒汉式(线程安全,性能差,不推荐这样写)
 *
 * 1.构造器私有
 * 2.定义一个静态变量存储一个单例对象(定义时不初始化该对象)
 * 3.提供一个静态同步方法返回单例对象,返回前先询问是否有,有则直接返回,没有则创建新的返回
 */
public class Singleton04 {

    public static Singleton04 instance;

    private Singleton04() {}

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

}

class Test04 {
    public static void main(String[] args) {
        Singleton04 s1 = Singleton04.getInstance();
        Singleton04 s2 = Singleton04.getInstance();
        System.out.println(s1 == s2); // true
    }
}

懒汉式(线程不安全,不推荐这样写):

/**
 * 懒汉式(线程不安全,不推荐这样写)
 *
 * 1.构造器私有
 * 2.定义一个静态变量存储一个单例对象(定义时不初始化该对象)
 * 3.提供一个静态方法返回单例对象,返回前先询问是否有,有则直接返回,没有则创建新的返回
 */
public class Singleton05 {

    public static Singleton05 instance;

    private Singleton05() {}

    public static Singleton05 getInstance() {
        if (instance == null) {
            // 性能得到了优化,但是依然不能保证第一次获取对象的线程安全
            synchronized (Singleton05.class) {
                instance = new Singleton05();
            }
        }
        return instance;
    }

}

class Test05 {
    public static void main(String[] args) {
        Singleton05 s1 = Singleton05.getInstance();
        Singleton05 s2 = Singleton05.getInstance();
        System.out.println(s1 == s2); // true / false
    }
}

懒汉式(线程安全):其实私有化构造器并不保险,存在反射攻击;还可能出现反序列化攻击的风险

/**
 * 懒汉式(线程安全)
 *
 * 1.构造器私有
 * 2.定义一个静态变量(用volatile修饰,保证可见性和禁止指令重排序)存储一个单例对象(定义时不初始化该对象)
 * 3.提供一个静态方法返回单例对象,返回前先询问是否有,有则直接返回,没有则创建新的返回
 */
public class Singleton06 {

    public static volatile Singleton06 instance;

    private Singleton06() {}

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

}

class Test06 {
    public static void main(String[] args) {
        Singleton06 s1 = Singleton06.getInstance();
        Singleton06 s2 = Singleton06.getInstance();
        System.out.println(s1 == s2); // true
    }
}

懒汉式(基于类的初始化实现延迟加载和线程安全的单例设计):存在反射攻击和反序列化攻击的风险

/**
 * 懒汉式(基于类的初始化实现延迟加载和线程安全的单例设计)
 *
 * 1.构造器私有
 * 2.提供一个静态内部类,里面提供一个常量存储一个单例对象
 * 3.提供一个静态方法返回静态内部类中的单例对象
 */
public class Singleton07 {

    /*private static int i = 0;
    private int j = 0;*/

    private Singleton07() {}

    // 静态内部类只有等到需要用到才会加载,在加载过程中JVM会获取一个锁,不会出现线程安全问题,且只加载一次
    /*静态内部类有一个局限性,只能访问外部类静态的变量,非静态的无法访问*/
    private static class Inner {
        private static final Singleton07 INSTANCE = new Singleton07();

        /*private void test() {
            i += 1;
            // j += 1; // 无法访问
        }*/
    }

    public static Singleton07 getInstance() {
        return Inner.INSTANCE;
    }

}

class Test07 {
    public static void main(String[] args) {
        Singleton07 s1 = Singleton07.getInstance();
        Singleton07 s2 = Singleton07.getInstance();
        System.out.println(s1 == s2); // true
    }
}

枚举实现单例:枚举本身已经实现了线程安全

/**
 * 枚举实现单例
 *
 * 枚举实际上是一种多例的模式,如果我们直接定义一个实例就相当于单例了
 */
public enum Singleton08 {
    INSTANCE;

    public Singleton08 getInstance() {
        return INSTANCE;
    }
}

class test08 {

    public static void main(String[] args) {
        Singleton08 s1 = Singleton08.INSTANCE.getInstance();
        Singleton08 s2 = Singleton08.INSTANCE.getInstance();
        System.out.println(s1 == s2); // true
    }

}

 

标签:getInstance,模式,public,instance,static,单例,class
来源: https://www.cnblogs.com/roadlandscape/p/12894259.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有