首页 > 编程语言 >Java设计模式-单例模式

Java设计模式-单例模式

时间:2023-04-28 16:01:12浏览次数:39  
标签:Singleton Java 模式 实例 线程 单例 设计模式 public

一、前言

单例模式是一种设计模式,它确保一个类只能创建一个实例,并提供一种全局访问这个实例的方式。在Java中,单例模式可以通过多种方式来实现,其中最常见的是使用私有构造函数和静态方法实现

img

二、基本语法

在Java中,实现单例模式的方式有多种,其中最常见的实现方式包括以下几种:

1、懒汉式单例模式

懒汉式单例模式指的是在第一次使用单例对象时才创建实例。具体实现方式是在getInstance()方法中判断实例是否已经被创建,如果没有则创建一个新实例并返回。懒汉式单例模式的缺点是线程不安全,在多线程环境下可能会创建多个实例。

public class Singleton {
    private static Singleton instance;
    
    private Singleton() {
        // 私有构造函数
    }
    
    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

2、饿汉式单例模式

饿汉式单例模式指的是在类加载时就创建实例,因此也被称为静态单例模式。具体实现方式是将实例化语句放在静态代码块中。由于在类加载时就创建了实例,因此不存在线程安全性问题。

public class Singleton {
    private static Singleton instance = new Singleton();
    
    private Singleton() {
        // 私有构造函数
    }
    
    public static Singleton getInstance() {
        return instance;
    }
}

3、双重检验锁单例模式

双重检验锁单例模式是一种线程安全的单例模式实现方式,它通过使用synchronized关键字来确保线程安全性。具体实现方式是在getInstance()方法中添加双重检验锁,这可以避免不必要的锁竞争和实例化。

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;
    }
}

4、静态内部类单例模式

静态内部类单例模式是一种比较常用的单例模式实现方式,它利用了静态内部类只会在被使用时才会加载的特点,从而避免了饿汉式单例模式的资源浪费和懒汉式单例模式的线程不安全问题。

public class Singleton {
    private static class SingletonHolder {
        private static final Singleton INSTANCE = new Singleton();
    }
    
    private Singleton() {
        // 私有构造函数
    }
    
    public static Singleton getInstance() {
        return SingletonHolder.INSTANCE;
    }
}

5、枚举单例模式

枚举单例模式是一种更为简单和安全的单例模式实现方式,它利用了Java中枚举类型本身就是单例的特点。枚举单例模式是一种天然线程安全的单例模式实现方式,而且可以防止反射和序列化等攻击。

public enum Singleton {
    INSTANCE;
    
    // 其他方法
}

6、ThreadLocal单例模式

ThreadLocal单例模式是一种可以在多线程环境下确保单例对象的线程安全单例模式实现方式。具体实现方式是在ThreadLocal中保存单例对象,每个线程都有自己的ThreadLocal副本,从而避免了线程安全性问题。

public class Singleton {
    private static final ThreadLocal<Singleton> INSTANCE = new ThreadLocal<Singleton>() {
        @Override
        protected Singleton initialValue() {
            return new Singleton();
        }
    };
    
    private Singleton() {
        // 私有构造函数
    }
    
    public static Singleton getInstance() {
        return INSTANCE.get();
    }
}

7、注册式单例模式

注册式单例模式指的是通过一个注册表来管理所有单例对象,从而实现单例模式。具体实现方式是在一个静态的Map中保存所有单例对象,然后在需要使用单例对象时通过Map来获取。

public class Singleton {
    private static Map<String, Singleton> instances = new HashMap<>();
    
    private Singleton() {
        // 私有构造函数
    }
    
    public static Singleton getInstance(String name) {
        if (!instances.containsKey(name)) {
            instances.put(name, new Singleton());
        }
        return instances.get(name);
    }
}

三、使用场景

单例模式通常在需要确保全局只有一个实例的场景中使用,例如:

  1. 线程池:在多线程环境下,线程池需要保证只有一个实例。
  2. 数据库连接池:同样地,数据库连接池也需要保证只有一个实例。
  3. 日志对象:日志对象通常是全局可见的,因此需要保证只有一个实例。
  4. 配置文件:在某些情况下,需要全局共享的配置文件也需要保证只有一个实例。

四、使用示例

下面是一个简单的例子,演示如何使用单例模式实现线程池:

public class ThreadPool {
    private static ThreadPool instance;
    
    private ThreadPool() {
        // 初始化线程池
    }
    
    public static synchronized ThreadPool getInstance() {
        if (instance == null) {
            instance = new ThreadPool();
        }
        return instance;
    }
    
    // 线程池相关的方法
}

在上述代码中,我们使用synchronized关键字来保证getInstance()方法的线程安全性。这意味着每次只有一个线程可以访问getInstance()方法,从而避免了多个线程同时创建线程池实例的问题。

四、常见问题

单例模式的实现有一些常见问题,需要注意:

  1. 线程安全性:如上所述,如果多个线程同时访问getInstance()方法,可能会导致多个实例的创建。因此,需要确保getInstance()方法是线程安全的,可以通过synchronized关键字来实现。
  2. 序列化问题:如果单例类实现了Serializable接口,那么在反序列化时可能会创建多个实例。解决方法是在类中添加readResolve()方法,并返回单例实例。
  3. 反射问题:通过反射机制,可以调用私有构造函数创建实例。解决方法是在构造函数中添加判断,如果已经存在实例则抛出异常

五、总结

单例模式是一种非常常用的设计模式,在多线程环境下,它可以确保只有一个实例被创建,并提供一种全局访问这个实例的方式。在Java中,可以通过私有构造函数和静态方法实现单例模式。在实现单例模式时,需要注意线程安全性、序列化问题以及反射问题。尽管单例模式非常有用,但也有一些缺点,例如它可能导致代码变得更加复杂,而且在多线程环境下可能会影响性能。因此,在使用单例模式时需要根据具体情况进行权衡。

标签:Singleton,Java,模式,实例,线程,单例,设计模式,public
From: https://www.cnblogs.com/xstxjs/p/17362438.html

相关文章

  • Java学习笔记(六)
    1、什么是JavaBean类是公共的有一个无参的公共的构造器有属性,且有对应的get、set方法  2、对单例模式的理解单例模式分为两种: 这种方式叫做饿汉式,是在类加载的时候就直接将对象创建了出来。还有一种懒汉式 懒汉式是在用到实例对象的时候才会将对象创建出来。但......
  • Java获取1688商品详情API接口示例说明
    ​ 在使用JavaWeb类的时候,如果我们需要获取一个网站中某个商品的详细信息,我们可以使用JavaScript来获取。我们可以用JavaScript来实现一个获取商品详情的API接口,来获取一个网站中某个商品的详细信息。在使用JavaScript进行接口请求时,可以使用下面的方法:通过javascript获......
  • JAVA AES 加密算法实现
    importjavax.crypto.Cipher;importjavax.crypto.spec.IvParameterSpec;importjavax.crypto.spec.SecretKeySpec;importjava.nio.charset.StandardCharsets;importjava.util.Base64;publicclassAESUtil{privatestaticfinalStringDEFAULT_KEY="hj7x......
  • Java 生成验证码
    后端:1、第一步生成验证码字符串privateStringgetCheckCode(){Stringbase="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";intsize=base.length();Randomr=newRandom();StringBuildersb=newStringBuilder();for(inti=1;i<=4;i+......
  • Could not create the Java virtual machine解决
    CouldnotcreatetheJavavirtualmachine解决原文链接:https://blog.csdn.net/weixin_42031680/article/details/118652127CouldnotcreatetheJavavirtualmachine的解决文章目录CouldnotcreatetheJavavirtualmachine的解决报错描述报错截图解决方案一:1.......
  • JavaFx 生成二维码工具类封装
    原文地址:JavaFx生成二维码工具类封装-Stars-One的杂货小窝之前星之音乐下载器有需要生成二维码功能,当时用的是一个开源库来实现的,但是没过多久,发现那个库依赖太多,有个http-client的依赖,把软件都搞大了一倍,而且有时候开发的时候下载依赖还报错,就想换个方案于是在网上......
  • java -jar XXX.jar 没有主清单属性以及找不到或无法加载主类的问题
    java-jarXXX.jar没有主清单属性以及找不到或无法加载主类的问题原文链接:https://blog.csdn.net/Mrzhuangr/article/details/124731024文章目录一、问题陈述二、解决方法1、方法一(问题没有真正解决)2、方法二(最终解决了问题)一、问题陈述环境:Idea2021jdk1.8......
  • Java 生成验证码
    1、第一步生成背景板publicvoidgenerateCheckCode(HttpServletRequestrequest,HttpServletResponseresponse)throwsIOException{//服务器通知浏览器不要缓存response.setHeader("pragma","no-cache");response.setHeader("cache-con......
  • Java中二进制与十进制转换
    转: Java中二进制与十进制转换 十进制转二进制(除2取余,直到商小于1,逆序排序)如138转二进制138÷2=69 余069÷2=34余134÷2=17余017÷2=8余18÷2=4余04÷2=2余02÷2=1余01÷2= 0余1然后逆序排序1 0  0  0......
  • 中级软件设计师软考备考资源;解决org.apache.ibatis.binding.BindingException: Invali
    中级软件设计师软考备考资源软考资源在百度网盘上org.apache.ibatis.binding.BindingException:Invalidboundstatement(notfound)问题即在mybatis中dao接口与mapper配置文件在做映射绑定的时候出现问题,简单说,就是接口与xml要么是找不到,要么是找到了却匹配不到。这是一个很容易......