Java的单例模式如何实现

发布时间:2022-02-23 15:31:20 作者:iii
来源:亿速云 阅读:144

这篇文章主要介绍“Java的单例模式如何实现”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Java的单例模式如何实现”文章能帮助大家解决问题。

什么是单例模式

单例模式的优缺点

优点

缺点

单例模式的实现

懒汉式

/**
  *Singleton类,单例模式类,在类加载时便会创建一个私有静态变量instance,也就是该类的实
  *例,再通过公共接口getInstance()来发布该实例
  */
public class Singleton {  
    private static Singleton instance;
    //私有化构造方法防止外界new对象
    private Singleton (){

    }

    //公有化静态函数,对外暴露单例对象的接口

    public static Singleton getInstance() {

        if (instance == null) {

            instance = new Singleton();

        }

        return instance;

    }

但是这种方式并不能保证这是唯一的单例,在高并发访问下,多个线程同时访问到这个单例时,还是有可能不能保证这个类就是单例的

为了保证线程安全,我们可以加锁,给这个getInstance()方法加上线程同步锁synchronize具体实现如下:

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

但是这种方式一旦加锁,虽然可以保证其实单例且线程安全的,但是在高并发访问下性能必然是受到影响,多个线程都需要用到该单例时,就无法保证速度,需要同步地等待这个单例使用完回到JVM中的堆区(Heap)才可以继续使用这个单例,效率十分的低。

还有一种是双重检查式,两次判断

Double Check Lock(DCL)方式实现单例模式

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

我们可以看到getInstance中对instance进行了两次判断是否为空,第一次判断主要是为了避免不必要的同步问题,第二次判断则是为了在null的情况下创建实例,因为在某些情况下会出现失效问题即DCL失效问题,可以使用volatile关键字处理这个问题,但是同样的,使用了volatile关键字也会对性能有一定的影响。但是优点在于资源利用率高,第一次执行getInstance时对象才被实例化,但是DCL也因为第一次加载时反应慢,所以在高并发情况下也会有一定的缺陷。

饿汉式

/**  *这种方式在类加载时就完成了初始化,所以类加载较慢,但是获取对象的速度快。这种方式  *基于类加载机制,避免了多线程的同步问题。如果从来没有使用过这个实例,则会造成内存  *的浪费。  */public class Singleton {      private static Singleton instance = new Singleton();      private Singleton (){            }      public static Singleton getInstance() {      	return instance;      }  }

匿名内部类/静态内部类

public class Singleton {    private static Singleton instance;    //静态块在类加载时会被执行,也就创建了Singleton类实例    static{        instance = new Singleton();    }    private Singleton (){        }      public static final Singleton getInstance() {      	return SingletonHolder.INSTANCE;      }  }
/**  *Java静态内部类的特性是,加载的时候不会加载内部静态类,使用的时候才会进行加载。  *第一次加载Singleton类时并不会初始化sInstance,只有第一次调用getInstance方法时虚  *拟机加载SingletonHolder并初始化sInstance。这样不仅能确保线程安全,也能保证  *Singleton类的唯一性。所以,推荐使用静态内部类单例模式  */public class Singleton {      private static class SingletonHolder {      	private static final Singleton INSTANCE = new Singleton();      }    private Singleton (){        }      public static final Singleton getInstance() {      	return SingletonHolder.INSTANCE;      }  }

枚举单例模式

/**
  *默认枚举实例的创建是线程安全的,并且在任何情况下都是单例。
  *枚举单例的有点就是简单,缺点是可读性不高。
  */
public enum Singleton {
    //外部调用由原来的Singleton.getInstance变成了Singleton.INSTANCE了。
    INSTANCE;
}

总结

单例模式是运用频率很高的模式,在我们客户端通常是没有高并发的情况,所以选择哪种方式并不会有太大的影响。出于效率考虑,推荐使用静态内部类的单例模式和DCL的单例模式。

优点:

缺点:

使用场景

关于“Java的单例模式如何实现”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识,可以关注亿速云行业资讯频道,小编每天都会为大家更新不同的知识点。

推荐阅读:
  1. java单例模式的实现方式以及差异
  2. java如何实现单例模式

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

java

上一篇:Java的String类怎么创建

下一篇:Java的冒泡排序如何实现

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》