单例模式的八种方式
- 饿汉式(静态常量)
- 饿汉式(静态代码块)
- 懒汉式(线程不安全)
- 懒汉式(线程安全,同步方法)
- 懒汉式(线程安全,同步代码块)
- 双重检查
- 静态内部类
- 枚举
饿汉式(静态常量)
步骤:
- 构造器私有化
目的:放置外部通过new的方式创建对象
- 在类的内部创建对象
因为禁止外部创建对象,所以在类的内部创建对象
- 对外暴露一个静态的公共方法,getInstance()
- 代码实现
public class singleton01 {public static void main(String[] args) {Singleton instance = Singleton.getInstance();Singleton instance1 = Singleton.getInstance();//测试1证明两个实例是一样的System.out.println(instance==instance1);//true//测试2通过hashCodeSystem.out.println(instance.hashCode()==instance1.hashCode());}}class Singleton{//1.构造器私有化private Singleton(){}//2.在类的内部创建对象实例private final static Singleton instance=new Singleton();//3.提供一个公有的静态对象,返回实例对象public static Singleton getInstance(){return instance;}}
- 优缺点
优点:写法比较简单,就是在类装载的时候完成了实例化,避免了线程同步的问题
缺点:在类装载的时候就完成了实例化,没有达到Lazy Loading(懒加载)的效果,如果从始至终从未使用 过这个实例,则会造成内内存的浪费
- 说明:这种方式是记忆classloader机制,避免了多线程的同步问题,不过,instance在类装载的时候就实例化了,在单例模式中,大多数都是调用getInstance方法,但是导致类装载的原因有很多种,因此,不能确定有其他方式(或着其他的静态方法)导致类装载,这时候初始化instance就没有达到Lazy Loading(懒加载)的效果
- 结论:这种单例模式可以用,但是可能造成内存浪费
饿汉式(静态代码块)
- 代码实现
public class singleton02 {public static void main(String[] args) {Singleton instance = Singleton.getInstance();Singleton instance1 = Singleton.getInstance();//测试1证明两个实例是一样的System.out.println(instance == instance1);//true//测试2通过hashCodeSystem.out.println(instance.hashCode() == instance1.hashCode());}}class Singleton {//1.构造器私有化private Singleton() {}//2.在类的内部创建对象实例private static Singleton instance;static {//在静态代码块中,创建单例对象instance = new Singleton();}//3.提供一个公有的静态对象,返回实例对象public static Singleton getInstance() {return instance;}}
- 优缺点:
这种方式和饿汉式(静态常量)方式是一样的,只不过将类的实例化的过程放在了静态代码块中,也是在类装载的时候,就执行静态代码块中的代码,初始化类的实例。优缺点和饿汉式(静态常量)一样
- 结论:这种单例模式可以用,但是可能造成内存浪费
