目录
  • 单例模式的介绍
  • 单例模式实现的八种方式
    • 饿汉式
      • 静态常量
      • 静态代码块
    • 懒汉式
      • 线程不安全的写法
      • 线程安全,同步锁—效率低,不推荐
      • 线程安全,同步代码块—无法解决线程安全问题,不推荐
    • 双重检查—解决线程安全和懒加载问题–推荐使用
      • 静态内部类—可以实现懒加载,线程安全,推荐使用
        • 枚举
        • 单例模式注意事项
          • 总结

            单例模式的介绍

            单例模式实现的八种方式

            饿汉式

            静态常量

            步骤:

            1.构造器私有化(防止new)

            2.类的内部创建对象

            3.向外暴露一个静态的公共方法—getInstance

            //饿汉式静态常量
            class Singleton
            {
              //构造器私有化,外部不能new
                private Singleton(){}
                //静态常量
                private final static  Singleton  instance=new Singleton();
                //提供一个公有的静态方法,返回一个实例对象
                public static Singleton getInstance()
                {
                 return instance;
                }
            }
            public class Main
            {
                public static void main(String[] args)
                {
                    Singleton s1=Singleton.getInstance();
                    Singleton s2=Singleton.getInstance();
                    System.out.println(s1.hashCode()==s2.hashCode());
                }
            }
            

            静态代码块

            //饿汉式静态常量
            class Singleton
            {
              //构造器私有化,外部不能new
                private Singleton(){}
                //静态常量
                private static  Singleton  instance;
                //在静态代码块中,创建单例对象
                static
                {
                 instance=new Singleton();
                }
                //提供一个公有的静态方法,返回一个实例对象
                public static Singleton getInstance()
                {
                 return instance;
                }
            }
            public class Main
            {
                public static void main(String[] args) {
                    Singleton s1=Singleton.getInstance();
                    Singleton s2=Singleton.getInstance();
                    System.out.println(s1.hashCode()==s2.hashCode());
                }
            }
            

            静态代码块的优缺点

            懒汉式

            线程不安全的写法

            class Singleton
            {
              //构造器私有化,外部不能new
                private Singleton(){}
                //静态常量
                private static  Singleton  instance;
                //提供一个公有的静态方法
                //当使用该方法时,才去创建实例对象
                //即懒汉式
                public static Singleton getInstance()
                {
                    if(instance==null)
                    {
                        instance=new Singleton();
                    }
                 return instance;
                }
            }
            public class Main
            {
                public static void main(String[] args) {
                    Singleton s1=Singleton.getInstance();
                    Singleton s2=Singleton.getInstance();
                    System.out.println(s1.hashCode()==s2.hashCode());
                }
            }
            

            优缺点

            线程安全,同步锁—效率低,不推荐

            class Singleton
            {
              //构造器私有化,外部不能new
                private Singleton(){}
                //静态常量
                private static  Singleton  instance;
                //提供一个公有的静态方法
                //当使用该方法时,才去创建实例对象
                //即懒汉式
                //给当前静态方法加上一个同步锁,这样所有的对象就是一把锁
                //多个对象同时调用此方法,会按顺序依次调用
                public static synchronized Singleton getInstance()
                {
                    if(instance==null)
                    {
                        instance=new Singleton();
                    }
                 return instance;
                }
            }
            public class Main
            {
                public static void main(String[] args) {
                    Singleton s1=Singleton.getInstance();
                    Singleton s2=Singleton.getInstance();
                    System.out.println(s1.hashCode()==s2.hashCode());
                }
            }
            

            优缺点

            线程安全,同步代码块—无法解决线程安全问题,不推荐

            class Singleton
            {
              //构造器私有化,外部不能new
                private Singleton(){}
                //静态常量
                private static  Singleton  instance;
                //提供一个公有的静态方法
                //当使用该方法时,才去创建实例对象
                //即懒汉式
                public static  Singleton getInstance()
                {
                    if(instance==null)
                    {
                        //锁的是代码块
                        //锁的对象是当前类的字节码文件对象,即当前类的所有势力对象拥有一把锁
                        synchronized(Singleton.class)
                        {
                            instance=new Singleton();
                        }
                    }
                 return instance;
                }
            }
            public class Main
            {
                public static void main(String[] args) {
                    Singleton s1=Singleton.getInstance();
                    Singleton s2=Singleton.getInstance();
                    System.out.println(s1.hashCode()==s2.hashCode());
                }
            }
            

            优缺点

            双重检查—解决线程安全和懒加载问题–推荐使用

            class Singleton
            {
              //构造器私有化,外部不能new
                private Singleton(){}
                //静态常量
                //volatile 保证变量在多线程下的可见性,即每个线程获取到当前变量的值是最新的值
                private static  volatile Singleton  instance;
                //提供一个公有的静态方法
                //当使用该方法时,才去创建实例对象
                public static  Singleton getInstance()
                {
                    //加入双重检查问题,解决线程安全,同时解决懒加载问题
                    if(instance==null)
                    {
                        //锁的是代码块
                        //锁的对象是当前类的字节码文件对象,即当前类的所有势力对象拥有一把锁
                        synchronized(Singleton.class)
                        {
                            if(instance==null)
                            {
                                instance=new Singleton();
                            }
                        }
                    }
                 return instance;
                }
            }
            public class Main
            {
                public static void main(String[] args) {
                    Singleton s1=Singleton.getInstance();
                    Singleton s2=Singleton.getInstance();
                    System.out.println(s1.hashCode()==s2.hashCode());
                }
            }
            

            优缺点

            静态内部类—可以实现懒加载,线程安全,推荐使用

            静态内部类在调用时,才会加载

            当一个Java类第一次被真正使用到的时候静态资源被初始化、Java类的加载和初始化过程都是线程安全的

            class Singleton
            {
              //构造器私有化,外部不能new
                private Singleton(){}
            //静态内部类
                private static class SingletonInstance{
                    //静态属性
                    private static final Singleton INSTANCE=new Singleton();
            }
                public static  Singleton getInstance()
                {
                    //该方法调用时,静态内部类加载,里面的静态属性才会赋值
                    return SingletonInstance.INSTANCE;
                }
            }
            public class Main
            {
                public static void main(String[] args) {
                    Singleton s1=Singleton.getInstance();
                    Singleton s2=Singleton.getInstance();
                    System.out.println(s1.hashCode()==s2.hashCode());
                }
            }
            

            优缺点

            枚举

            enum Singleton
            {
                //枚举常量
                INSTANCE;
                //底层: public static final Singleton INSTANCE= new Singleton ();
                //方法
                public void getInstance()
                {
                    System.out.println("得到实例");
                }
            }
            public class Main
            {
                public static void main(String[] args) {
                    Singleton s1=Singleton.INSTANCE;
                    Singleton s2=Singleton.INSTANCE;
                    s1.getInstance();
                    s2.getInstance();
                    System.out.println(s1.hashCode()==s2.hashCode());
                }
            }
            

            优缺点

            单例模式注意事项

            总结

            本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注的更多内容!