单例模式 -- 懒汉模式&饿汉模式

目录

一、单例模式是什么?

二、饿汉模式

三、懒汉模式

一、单例模式是什么?

单例模式是一种设计模式,用于将类的实例化限制为一个对象。它确保一个类只有一个实例,并提供了该实例的全局访问点。这种模式被广泛用于创建对象的唯一实例,例如数据库连接和日志记录器等。单例模式可以在多线程环境下使用,确保多个线程访问同一个实例时不会发生冲突。常见的实现方式包括懒加载、饿汉式和双重检查等。

二、饿汉模式

饿汉模式是一种单例模式的实现方式,它的特点是在程序启动时就进行对象的实例化。在这种实现方式中,单例对象会在类加载时就被创建出来,因此也被称作“饱汉模式”或者“静态常量方式”。

饿汉模式的优点是实现简单、线程安全,无需考虑多线程环境下的同步问题。其缺点是无法进行懒加载,带来了一定的系统资源开销。在某些场景下,如果单例对象很大或者初始化耗时较长,饿汉模式的开销可能会比较明显。

class Singleton{
    Singleton singleton = new Singleton();
    public Singleton getSingleton() {
        return singleton;
    }
    private Singleton(){}
}

三、懒汉模式

懒汉模式是一种单例模式的实现方式,它的特点是在首次访问单例对象时才进行对象的实例化。懒汉模式的优点是可以避免在程序启动时就进行对象的实例化,节省了系统的资源。懒汉模式的缺点是在多线程环境下,可能会出现线程安全问题,需要额外的同步措施来保证线程安全性。

例如,以下是一个简单的懒汉模式实现:

class Singleton{
    private static Singleton singleton = null;
    public Singleton getSingleton() {
        if (singleton==null){
            this.singleton = new Singleton();
        }
        return singleton;
    }
    private Singleton(){}
}
上面的懒汉模式的实现是线程不安全的.
线程安全问题发生在首次创建实例时. 在多个线程中同时调用 getSingleton 方法,可能两个线程会同时进行new操作 , 这样我们多线程创建了多个对象 , 就不是单例模式了 , 主要导致该问题的是由于这里面涉及到了对singleton的修改操作,失去了原子性,为了保证原子性,我们想到了加锁,从而实现线程安全问题。
我们为了解决这个多线程竞争的安全问题我们可以进行加锁操作 如下面代码
class Singleton{
    private static Singleton singleton = null;
    synchronized public Singleton getSingleton() {
        if (singleton==null){
            this.singleton = new Singleton();
        }
        return singleton;
    }
    private Singleton(){}
}

但是现在在我们进行 new 操作的时候可能会触发指令重排序 , 所以我们为了避免这个情况还需要对代码进行修改

class Singleton{
    volatile private static Singleton singleton = null;
     public Singleton getSingleton() {
         if (singleton==null){
             synchronized(Singleton.class){
                 if (singleton==null){
                     this.singleton = new Singleton();
                 }
             }
         }
         return singleton;
     }
    private Singleton(){}
}
  • 这里我们使用双if减少不必要的加锁操作
  • 加锁是为了把if和变成原子操作
  • 使用volatile禁止指令重排序

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