Java单例模式的五种写法

本文详细介绍了Java单例模式的五种写法,包括饿汉式、懒汉式、双重检查模式、静态内部类写法和枚举式。每种方式在内存使用、线程安全和懒加载方面各有特点。饿汉式和静态代码块在类加载时即创建实例,可能造成内存浪费;懒汉式在多线程环境下可能导致实例化多次;双重检查模式兼顾线程安全和懒加载;静态内部类写法延迟加载但不保证线程安全;枚举式为最安全的实现,防止反序列化和反射攻击。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

单例模式:一个类只能有一个实例,并且提供一个全局可以访问的入口,好处:节省内存,节省计算,如当一个类才初始化的时候做了很多操作(读取数据库数据,而且数据库数据不变),那全局用同一个实例就行,每次都创建一个新的实例属于浪费资源

  • 单例模式的适用场景:
    • 1、无状态工具类,如日志工具,字符串工具
    • 2、全局信息类,如全局计数,环境变量

第一种写法

饿汉式:在类加载时就创建了实例,而没有使用懒加载的方式,如果自始至终都没有使用这个实例,就造成了内存的浪费

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

静态代码块形式:与饿汉式有同样的缺点

public class Singleton {
    private static Singleton singleton;

    static {
        singleton = new Singleton();
    }

    private Singleton() {
    }

    public static Singleton getInstance() {
        return singleton;
    }
}

第二种写法

懒汉式:这种方法在getInstance方法调用时才去实例化对象,起到了懒加载的效果,但是只能在单线程下使用,如果在多线程下,一个线程刚进入了if判断就被阻塞,另外一个线程进入if后创建实例,而第一个线程执行时会再次创建实例,所以在多线程情况下不能使用这种情况

public class Singleton {
    private static Singleton singleton;

    private Singleton() {
    }

    public static Singleton getInstance() {
        if (singleton == null) {
            singleton = new Singleton();
        }
        return singleton;
    }
}

加入synchronized关键字可以解决这个问题,但是效率低

public class Singleton {
    private static Singleton singleton;

    private Singleton() {
    }

    public static synchronized Singleton getInstance() {
        if (singleton == null) {
            singleton = new Singleton();
        }
        return singleton;
    }
}

第三种写法

双重检查模式:将synchronized关键字放在方法体中,同时判断两次就可以避免创建两次实例,不仅线程安全,而且懒加载

public class Singleton {
    private static volatile Singleton singleton;

    private Singleton() {
    }

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

第四种写法

静态内部内写法:与饿汉式的区别就是,在类加载时并不会直接实例化对象

public class Singleton {
    private Singleton() {
    }

    private static class SingletonInstance {
        private static final Singleton singleton = new Singleton();
    }

    public static Singleton getInstance() {
        return SingletonInstance.singleton;
    }
}

第五种写法

枚举式:在effective java中说道,最佳的单例实现模式就是枚举模式,不仅能避免多线程同步的问题,还能防止反序列化和反射创建新的对象来破坏单例的情况

public enum Singleton {
    INSTANCE;

    public void doSomething() {
        System.out.println("doSomething");
    }

}

调用方法:

public class Main {
    public static void main(String[] args) {
        Singleton.INSTANCE.doSomething();
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值