学习单例模式

作者·:爱塔居

专栏:JavaEE

作者简介:大三学生,希望和大家一起进步

学习单例模式_第1张图片

文章目录

文章目录

前言

一、饿汉模式

二、懒汉模式


前言

单例模式是校招中最常考的设计模式之一。

单例模式能保证某个类在程序中只存在唯一一份实例,而不会创建出多个实例。

单例指的是单个实例(instance)对象。类的实例,就是对象。Java中的单例模式,借助java语法,保证某个类,只能够创建出一个实例,而不能new多次。

单例模式具体的实现方式,分为“饿汉”和“懒汉”两种。


一、饿汉模式

类加载的同时,创建实例:

//把这个类设定为单例,饿汉
class Singleton{
    //唯一的实例的实体
private static Singleton instance=new Singleton();
//被static修饰,该属性是类的属性。JVM中,每个类的类对象只有唯一一份,类对象里的这个成员自然也是唯一一份了。
//获取到实例的方法
    public static Singleton getInstance(){
        return instance;
    }
    //禁止外部new实例
    private Singleton(){};
}
public class test {
    public static void main(String[] args) {
    Singleton s1=Singleton.getInstance();
    Singleton s2=Singleton.getInstance();
    }
 
    }
 

二、懒汉模式

类加载的时候不创建实例。第一次使用的时候才创建对象。就跟挤牙膏一样,你需要的时候再挤出来,不用就不挤。

//把这个类设定为单例模式中的懒汉模式。
class SingletonLazy{
private static SingletonLazy instance=null;
    public static SingletonLazy getInstance(){
      if(instance==null){
          instance=new SingletonLazy();
      }
      return instance;
    }
    private SingletonLazy(){};
}
public class test {
    public static void main(String[] args) {
    SingletonLazy s1=SingletonLazy.getInstance();
    SingletonLazy s2=SingletonLazy.getInstance();
        System.out.println(s1==s2);
    }
    }

在单线程中,饿汉模式和懒汉模式是线程安全的。

在多线程中,懒汉模式可能无法保证创建对象的唯一性。

 进行加锁,保证判定操作和new操作是原子性的。

class SingletonLazy{
private static SingletonLazy instance=null;
    synchronized public static SingletonLazy getInstance(){
      if(instance==null){
          instance=new SingletonLazy();
      }
      return instance;
    }
    private SingletonLazy(){};
}
public class test {
    public static void main(String[] args) {
    SingletonLazy s1=SingletonLazy.getInstance();
    SingletonLazy s2=SingletonLazy.getInstance();
        System.out.println(s1==s2);
    }
    }

因为加锁/解锁是一件开销比较高的事情,而懒汉模式的线程不安全只是发生在首次创建实例的时候,因此后续使用的时候,就不必再进行加锁了。

外层的if就是判定下看当前是否已经把instance实例创建出来了。

同时为了避免“内存可见性”导致读取的instance出现偏差,于是补充上volatile。

当多线程首次调用getInstance,大家可能都发现instance为null,于是又继续往下执行来竞争锁。其中竞争成功的线程,再完成创建实例的操作。

当这个实例创建完了之后,其他竞争倒锁的线程就被里层if挡住了,也就不会继续创建其他实例。

以下代码在加锁的基础上,做出了进一步的改动:

1.使用双重if判定,降低锁竞争的概率

2.给instance加上了volatile

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

你可能感兴趣的:(JavaEE,java,单例模式)