加入收藏 | 设为首页 | 会员中心 | 我要投稿 沧州站长网 (https://www.0317zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 教程 > 正文

设计模式之单例模式分析

发布时间:2021-12-05 09:25:12 所属栏目:教程 来源:互联网
导读:定义:Ensure a class has only one instance, and provide a global point of access to it.(确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。) 1.饿汉式 public class Singleton { private static final Singleton INSTANCE = new S

定义:Ensure a class has only one instance, and provide a global point of access to it.(确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。)
 
1.饿汉式
 
public class Singleton {
 
    private static final Singleton INSTANCE = new Singleton();
 
    private Singleton(){}
 
    public static Singleton getInstance(){
        return INSTANCE;
    }
 
    public void method(){
        System.out.println("普通方法");
    }
 
    public static void main(String[] args) {
        Singleton instance1 = Singleton.getInstance();
        Singleton instance2 = Singleton.getInstance();
        System.out.println(instance1 == instance2);
    }
}
此种方式在工作中最为简单常用。类加载到内存后,就只被实例化一次,所以只会产生一个实例,JVM保证线程安全。唯一的缺点是不管用到与否,都会在类加载的时候完成实例化。
 
2.懒汉式
 
public class SingletonLazy {
 
    private static volatile SingletonLazy INSTANCE;
 
    private SingletonLazy(){}
 
    public static SingletonLazy getInstance(){
        if (INSTANCE == null){
            synchronized (Singleton.class){
                if (INSTANCE == null){
                    INSTANCE = new SingletonLazy();
                }
            }
        }
        return INSTANCE;
    }
 
    public void method(){
        System.out.println("普通方法");
    }
 
    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            SingletonLazy instance = SingletonLazy.getInstance();
            new Thread(()-> System.out.println(instance.hashCode())).start();
        }
    }
}
此种方式虽然达到了按需初始化的目的,但是带来了线程不安全的问题,所以通过加锁的方式解决,但是又带来效率下降的问题,另外变量需要添加volatile关键字,防止指令重排序。
 
3.静态内部类
 
public class SingletonInner {
 
    private SingletonInner(){}
 
    private static class SingletonInnerHolder{
        private static final SingletonInner INSTANCE = new SingletonInner();
    }
 
    public static SingletonInner getInstance(){
        return SingletonInnerHolder.INSTANCE;
    }
 
    public void method(){
        System.out.println("普通方法");
    }
 
    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            SingletonInner instance = SingletonInner.getInstance();
            new Thread(()-> System.out.println(instance.hashCode())).start();
        }
    }
}
此种方式解决了上面两种方式的问题,当SingletonInner类被加载的时候,SingletonInnerHolder内部类是不会被加载的,只有在调用getInstance()的时候才会被加载,既达到了懒加载,又保证了只有一个实例。
 
4.枚举方式
 
public enum  SingletonEnum {
 
    INSTANCE;
 
    public void method(){
        System.out.println("普通方法");
    }
 
    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            new Thread(()->              System.out.println(SingletonEnum.INSTANCE.hashCode())).start();
        }
    }
}
此种方式不仅可以解决线程同步问题,还可以防止反序列化,因为枚举类没有构造方法。

(编辑:沧州站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读