首页 > 编程语言 > java设计模式之(单例模式)

java设计模式之(单例模式)

时间:2023-06-10 20:31:36浏览次数:43  
标签:java private instance 实例 static 单例 线程 设计模式 public

单例模式(懒汉式和饿汉式)

       在Java中指的是单例设计模式 他是软件开发中最常用的设计模式之一。

单:唯一

例:实例

单例设计模式: 既某个类在整个系统中只能有一个实例对象可被获取和使用的代码模式

要点:

    1.某个类只能有一个实例 

        构造器私有

    2.它必须自行创建这个实例

        含有一个该类的静态变量来保存这个唯一的实例

    3.它必须自行向整个系统提供这个实例

        1.直接暴露 2.用静态变量的get方法来获取


常见的单例形式

饿汉式: (直接创建对象 不存在线程安全问题)

    1.直接实例化饿汉式 (简单直观)

/**

* 饿汉式:

* 在类初始化时直接创建实例对象 不管你是否需要这个对象都会创建 

*

*/

public class Singleton1 {

    public static final Singleton1 INSTANCE=new Singleton1();

    private Singleton1(){} 

}

  2.枚举式 (最简洁) 

/** 

* 饿汉式 枚举类型:表示该类型的对象是有限的几个 

* 我们可以限定一个,就成单例

*/

public enum Singleton2 {

    INSTANCE

}

    3.静态代码块饿汉式 (适合复杂实例化)

/**

* 饿汉式 静态代码块 方式

* 适用于 比较复杂 需要度一堆初始化数据才能将对象创建好的

*/

public class Singleton3 {

    public static final Singleton3 INSTANCE;

    static {

        INSTANCE = new Singleton3();

    } 

    private Singleton3() {


    }


}

创建实例:

public class Test {

    public static void main(String[] args) {

        Singleton1 s = Singleton1.INSTANCE;

        Singleton2 s2 = Singleton2.INSTANCE;

        Singleton3 s3 = Singleton3.INSTANCE;

        System.out.println(s);

        System.out.println(s2);

        System.out.println(s3);

    }

}

饿汉式为什么不存在线程安全问题?

因为:

       类加载的方式是按需加载,且只加载一次。因此,在上述单例类被加载时,就会实例化一个对象并交给自己的引用,供系统使用。换句话说,在线程访问单例对象之前就已经创建好了。再加上,由于一个类在整个生命周期中只会被加载一次,因此该单例类只会创建一个实例,也就是说,线程每次都只能也必定只可以拿到这个唯一的对象。因此就说,饿汉式单例天生就是线程安全的。


懒汉式: (需要时创建对象(延迟创建对象) 存在线程安全问题)

    1.线程不安全 (适用于单线程)

/**

* 懒汉式 延迟创建对象

*  私有构造器用

*  用一个静态变量来保存这个唯一实例

*  提供一个静态方法 获取这个实例

*/

public class Singleton4 {

    private static  Singleton4 instance = null;

    private Singleton4(){}

    public static Singleton4 getInstance(){

        if(instance==null){ 

            instance = new Singleton4();

        }

        return instance;

    }

}

2.线程安全 (适用于多线程)

/**

*   第一种

* 懒汉式 延迟创建对象 (线程安全)

*/

public class Singleton5 {

    private static Singleton5 instance = null;

    private Singleton5(){}

    //在方法上加锁(synchronized) 保证线程安全 在高并发的情况下这种效率比较低 

    public synchronized static Singleton5 getInstance(){

        if(instance==null){

            instance = new Singleton5();

        }

        return instance;

    }

}



/**

* 第二种 DoubleCheck

* 懒汉式 延迟创建对象

*/

public class Singleton6 {

    //加上volatile 保证jvm 不会对代码进行重排序

    private static volatile Singleton6 instance = null;

    private Singleton6(){}

    //保证线程安全 doublecheck

    public  static Singleton6 getInstance(){

        //在线程运行中如果 instance本身不同于空 那样的话就没必要继续进入锁 (效率高于给方法直接上锁)

        if(instance==null){

            synchronized (Singleton6.class){

                if(instance==null){

                    instance = new Singleton6();

                }

            }

        }

        return instance;

    }

}

3.静态内部类形式 (适用于多线程)

/**

* 在内部类被加载和初始话的时, 才创建INSTANCE实例对象

* 静态内部类不会自动随着外部类的加载和初始化而初始化,它是要单独去加载和初始化的

* 因为是在内部类加载时和初始话时才创建对象 因此是线程安全的

*/

public class Singleton7 {

    private Singleton7(){}

    private static class inner{

        private static final Singleton7 INSTANCE=new Singleton7(); 

    }

    public static Singleton7 getInstance(){

        return inner.INSTANCE;

    }

}

标签:java,private,instance,实例,static,单例,线程,设计模式,public
From: https://blog.51cto.com/u_15558311/6455379

相关文章

  • 转:设计模式之美
    转自:https://juejin.cn/post/71230293553656627341.概述1.1学习导读本文是极客时间专栏《设计模式之美》的学习笔记,详情请看原文。学习算法:是为了写出高效的代码;学习设计模式:是为了写出高质量(可扩展、可读、可维护)的代码;1.2为什么学习设计模式应对面试,算法、设计......
  • Java编程技巧-定义集合常量、定义数组常量的最佳方式
    场景Java中定义集合常量的最佳方式在编码中,经常使用到各种集合常量,比如List(列表)常量、Set(集合)常量、Map(映射)常量等。普通方式一般这样写:publicstaticfinalList<Integer>CONST_VALUE_LIST=Arrays.asList(1,2,3);publicstaticfinalSet<Integer>CONST_VALUE......
  • JavaBean中Boolean类型的字段名不要用isXxx(转)
    addbyzhj: 之前看阿里出品的Java开发手册中提到JavaBean中Boolean类型字段名不要用isXxx命名,一直不明白原因。这篇文章详细说明了原因。我对原文略微进行了修改,将fastjson库改为fastjson2,但对序列化反序列化结果没有影响。原文:https://mp.weixin.qq.com/s/b1q779XdWyRe0QyGxh......
  • 小米java软件开发面经
    面试转载面经小米java软件开发:一面50分钟左右:面试题:1、介绍下项目。2、使用Redis存储手机验证码以及检查是否过期的功能,展开说一下。3、Redis如何清除过期数据?4、Redis的持久化机制。5、RDB和AOF方式有什么区别?为什么提供第三种混合方式?6、Redis缓存异常的三......
  • Java开发技巧-数据结构-使用HashSet判断主键是否存在、使用Pair成对结果返回/Triple三
    场景Java中使用HashSet判断主键是否存在HashSet实现Set接口,由哈希表(实际上是HashMap)实现,但不保证set的迭代顺序,并允许使用null元素。HashSet的时间复杂度跟HashMap一致,如果没有哈希冲突则时间复杂度为O(1),如果存在哈希冲突则时间复杂度不超过O(n)。所以,在日常编码中,可以使用HashSe......
  • 设计模式的概念
    设计模式简介设计模式是一种最佳实践长期以来总结出来的解决一系列问题的一种套路。使用设计模式的目的:代码重用、工程化设计模式一般有多少种:23种、不设上限设计模式的类型设计模式的类型一共有四种:1.创建型设计模式:创建对象的同事隐藏创建的业务逻辑★工厂模式、★单......
  • java——微服务——spring cloud——Nacos——Nacos认识与安装
                   Nacos开发必知Nacos开发必知官网:https://nacos.io/zh-cn/index.htmlNocas文档:https://nacos.io/zh-cn/docs/what-is-nacos.htmlNocas下载:https://github.com/alibaba/nacos/releases  说明:1.4.0以下使用的mysql驱......
  • Java--进阶
    高级文本处理Locale类 //返回Java所支持的全部国家和语言的数组 Locale[]localeList=Locale.getAvailableLocales(); for(Localelocale:localeList) { System.out.println(locale.getLanguage()+"_"+locale.getCountry()); System.out.println(loc......
  • JAVA基础语法
    Day03Java基础语法1.运算符运算符:对字面量或者变量进行操作的符号表达式:用运算符把字面量或者变量连接起来符合java语法的式子就可以称为表达式。不同运算符连接的表达式体现的是不同类型的表达式例如:inta=10;intb=20;intc=a+b;+就叫做运算符a+b就叫表......
  • IDEA编译和构建JavaWeb项目时,项目中没有target目录,且out目录下classes文件下main包下
    问题如下:1.我们在添加web框架时,如图:2.在添加完框架,和配置完Tomcat我们开始运行项目,发现没有target文件和out文件下classes文件下什么都没有原因:出现这种情况,很可能是因为未加载的模块出现在了iml文件中,导致生成taget的时候出错,进而导致out文件内class文件的......