• Java中的单例模式


     一、饿汉式

    public class HungerySingleton {
     
     
        //ClassLoader 类加载时立即实例化对象,仅实例化一次,线程安全的
        private static HungerySingleton hungerySingleton = new HungerySingleton();
     
     
        public static HungerySingleton getInstance(){
            return hungerySingleton;
        }
     
        //利用线程输出(后面就不写了哈)
        public static void main(String[]args){
            for(int i=0;i<20;i++){
                Thread thread =new Thread() {
                    @Override
                    public void run() {
                        HungerySingleton hungerySingleton = HungerySingleton.getInstance();
                        System.out.println(hungerySingleton);
                    }
                };
                thread.start();
            }
        }
    }

    优点:仅实例化一次,线程是安全的。获取实例的速度快

    缺点:类加载时立即实例化对象,可能实例化的对象不被使用,造成内存的浪费。
     
     

    二、懒汉式

    public class HoonSingleton {
        //不能保证实例对象的唯一性
        private static HoonSingleton hoonSingleton = null;
     
     
        public static HoonSingleton getInstance(){
            if(hoonSingleton==null){
                hoonSingleton = new HoonSingleton();
            }
            return hoonSingleton;
        }
    }

    优点:获取实例时才进行实例的初始化,节省系统资源

    缺点:1、如果获取实例时,初始化的工作量较多,加载速度会变慢,影响系统系能
              2、每次获取实例都要进行非空检查,系统开销大
              3、非线程安全。注意红色代码标记,当多个线程同时getInstance()时,可能hoonSingleton实例化未完成,hoonSingleton==null判断均为true,造成对象重复实例化。
     
     

    三、双重检查锁 DCL(double-checked locking)+ volatile

    public class HoonSingleton {
     
        private static volatile HoonSingleton hoonSingleton = null;
     
        // 使用sync同步HoonSingleton.class 两次判断hoonSingleton是否为null 避免并发导致hoonSingleton被重新实例化
        // 并没有对整个方法使用sync,锁的粒度变小了,实现了实例对象的唯一性
        public static HoonSingleton getInstance(){
            if(hoonSingleton==null){
                synchronized (HoonSingleton.class) {
                    if(hoonSingleton==null) {
                        hoonSingleton = new DCL();
                    }
                }
            }
            return hoonSingleton;
        }

    优点:1、线程安全。注意加粗标记,进行双重检查,保证只在实例未初始化前进行同步,效率高。

              2、对hoonSingleton使用volatile修饰符,避免实例化过程中产生的重排序。避免NPE抛出。
    缺点:实例非空判断,耗费一定资源
     
     

    四、Holder方式 广泛使用的一种单例模式

    //声明类的时候、成员变量中不声明实例变量,而是放到内部静态类中
    public class HolderDemo {
     
        private static class Holder{
            private static HolderDemo instance = new HolderDemo();
        }
     
        public static HolderDemo getInstance(){
            return Holder.instance;
        }
    }

    优点:1、内部类只有在外部类被调用才加载,从而实现了延迟加载

              2、线程安全。且不用加锁。
     
     
     

    五、使用枚举的单例模式,本质上和饿汉模式没有任何区别,只是采用Enum实现的更巧妙了

    public enum EnumSingleton {
        //枚举类型,在加载的时候实例化。
        INSTANCE;
        public static EnumSingleton getInstance(){
            return INSTANCE;
        }
    }

    优点:仅实例化一次,线程是安全的。获取实例的速度快

    缺点:类加载时立即实例化对象,可能实例化的对象不被使用,造成内存的浪费。
     
     

    六、枚举和懒汉模式相结合

    public class EnumSingletonDemo {
     
        private enum EnumHolder{
            INSTANCE;
            private static  EnumSingletonDemo instance=null;
      
            private EnumSingletonDemo getInstance(){
                if(instance ==null) {
                    instance = new EnumSingletonDemo();
                }
                return instance;
            }
        }
      
        //实现懒加载
        public static EnumSingletonDemo  getInstance(){
            return EnumHolder.INSTANCE.getInstance();
        }

    优点:1、线程安全。且不用加锁。

              2、实现了懒加载
    缺点:仍然需要实例非空判断,耗费一定资源
     
     
     
     
  • 相关阅读:
    srvany.exe和instsrv.exe_2
    srvany.exe和instsrv.exe
    C# “国密加密算法”SM系列的C#实现方法
    DMZ讲解
    java 判断字符串是否为json格式
    MFC DrawText如何使多行文字居中显示 Demo
    C++ 实现一个日志类
    数据库两个神器【索引和锁】
    CentOS 7.*编译安装PHP8
    Centos添加永久环境变量
  • 原文地址:https://www.cnblogs.com/LemonFive/p/11149034.html
Copyright © 2020-2023  润新知