您的位置 首页 java

Java之单例模式(Singleton)

1.结构和原理

一个最基本的单例模式类包含一个私有的 静态变量 、一个私有的 构造函数 和和一个共有的静态函数。其中私有构造函数保证了该类不能通过构造函数来实例化,只能通过共有的静态函数返回一个唯一的私有静态变量。

2.实现单例模式

  • 懒汉模式———线程不安全
public class Singleton{
 private static Singleton instance;
 private Singleton(){}
 public static Singleton getInstance(){
 if(instance == null){
 instance = new Singleton();
 }
 return instance;
 } 
}
 
  • 在上述实现中,私有静态变量instance被延迟实例化,这样做的好处是在实际项目中,如果Singleton类没有被使用到,它就不会被实例化,从而减小系统开销。

注意:懒汉模式在 多线程 环境中是不安全的,例如当前有 n 个线程同时执行 getInstance () 方法时,此时的instance都为null,那么 Singleton 类就会被实例化 n 次。这与单例模式的设计初衷相悖。

  • 饿汉模式——— 线程安全
public class Singleton{
 private static Singleton instance = new Singleton();
 private Singleton(){}
 public static Singleton getInstance(){
 return instance;
 }
}
 

备注:在懒汉模式中,线程不安全是由于instance被多次实例化所造成的,在饿汉模式中直接实例化 Singleton 就解决了线程不安全问题。但是这种方式就失去了延迟实例化的好处。

  • 双重校验锁模式———线程安全
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;
 } 
}
 
  • 在双重校验锁模式下,双重锁先判断instance是否被实例化,如果instance没有被实例化,则将实例化instance的语句进行加锁操作,只有当instance真正为null时,才去实例化Singleton。instance只会被实例化一次,之后将不会被再次实例化。

说明:volatile关键字的作用是在多线程环境下,禁止JVM的指令重排列

  • 静态内部类模式
public class Singleton{
 private Singleton(){}
 public static Singleton getInstance(){
 return SingletonProvider.INSTANCE;
 }
 public static class SingletonProvider{
 private static final Singleton INSTANCE = new Singleton();
 }
}
 

静态内部类模式与饿汉模式有异曲同工之处

  • 枚举模式
public enum Singleton{
 INSTANCE;
 private String name;
 //getter()...
 // setter()...
 // otherMethod()...
}
 
  • 使用方式:
public class UserEnumSingleton{
 Singleton instance = Singleton.INSTANCE;
 instance.setName("example");
  System .out.println(instance.getName());
 Singleton instance2 = Singleton.INSTANCE;
 instance2.setName("example2");
 System.out.println(instance2.getName());
 instance.otherMethod();
 //other options...
 //使用java反射原理操作
 try{
 Singleton[] enums = Singleton.class.getEnumConstants();
 for(Singleton instance : enums){
 System.out.println(instance.getName());
 }
 }catch(Exception e){
 e.printStackTrace();
 }
}
 
  • 控制台输出结果:
example
example2
example2
 
  • 借助JDK的枚举来实现单例模式,不仅能够避免多线程同步问题,而且还能防止反序列化重新创建新的对象。

3.总结

优点

单例模式使得应用系统中一个类只被实例化一次,节省系统资源开销,对于系统中需要频繁创建和销毁的对象,使用单例模式可以在一定程度上提高系统的性能。

缺点

由于采用单例模式对类进行设计,就必须要记住获取对象的入口,即共有的静态函数名,而不是采用new关键字进行类的实例化,这在多人协同开发的项目中会给开发人员带来一些困扰(看不到源码),因此需要统一编码规范。

适用的范围

  • 需要频繁的进行创建和销毁的类
  • 实例化过程中耗费时间过长、占用资源过多且被频繁调用的类
  • 频繁操作I/O流或者访问数据库的类
  • 应用中定义的工具类

文章来源:智云一二三科技

文章标题:Java之单例模式(Singleton)

文章地址:https://www.zhihuclub.com/182397.shtml

关于作者: 智云科技

热门文章

网站地图