📜  Java中的Singleton单例类(1)

📅  最后修改于: 2023-12-03 14:42:55.353000             🧑  作者: Mango

Java中的Singleton单例类

在Java中,单例模式是一种常用的设计模式,它保证一个类只有一个实例,并且提供了一个全局的访问点。常用的实现方法是使用一个私有的构造函数、一个私有的静态变量以及一个公有的静态方法来实现。

实现方式一:饿汉式

在这种实现方式中,单例类在程序启动时就被创建,所以也叫做“线程安全的单例模式”。

示例代码:

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

优点:简单直接,线程安全。

缺点:单例对象在程序启动时就被创建出来,如果该对象比较大,或者单例类的构造函数比较耗时,这种实现方式就会影响程序的启动时间和性能。

实现方式二:懒汉式

在这种实现方式中,单例类的实例是在第一次被访问时才被创建,所以也叫做“延迟加载的单例模式”。

示例代码:

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

优点:避免了在程序启动时就创建对象,节约了一些资源。

缺点:在多线程环境下,可能会出现多个实例的情况,所以需要加锁来保证线程安全,但是加锁也会影响性能。

实现方式三:双重检查锁式

在这种实现方式中,单例类的实例是在第一次被访问时才被创建,同时采用双重检查锁的方式来保证线程安全。

示例代码:

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

优点:采用了双重检查锁的方式来保证线程安全,同时还避免了每次访问getInstance方法都要加锁的问题,提高了性能。

缺点:由于JVM内存模型的问题,偶尔会出现单例对象还未完全初始化的情况,需要对instance变量加上volatile关键字来避免这种情况。

实现方式四:静态内部类式

在这种实现方式中,单例类的实例是在第一次被访问时才被创建,同时使用静态内部类的方式来保证线程安全。

示例代码:

public class Singleton {
    private Singleton() {}
    
    private static class SingletonHolder {
        private static final Singleton instance = new Singleton();
    }
    
    public static Singleton getInstance() {
        return SingletonHolder.instance;
    }
}

优点:采用了静态内部类的方式来保证线程安全,同时还避免了每次访问getInstance方法都要加锁的问题,提高了性能。

缺点:需要了解静态内部类的使用方法,不够直观。