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

JAVA 单例设计模式

时间:2023-09-27 17:15:00浏览次数:37  
标签:设计模式 JAVA 对象 Dog 实例 线程 单例 多线程

单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

单例模式是一种创建型设计模式,它确保一个类只有一个实例,并提供了一个全局访问点来访问该实例。

注意:

  • 1、单例类只能有一个实例。

  • 2、单例类必须自己创建自己的唯一实例。

  • 3、单例类必须给所有其他对象提供这一实例。

介绍

意图:保证一个类仅有一个实例,并提供一个访问它的全局访问点。

主要解决:一个全局使用的类频繁地创建与销毁。

何时使用:当您想控制实例数目,节省系统资源的时候。

如何解决:判断系统是否已经有这个单例,如果有则返回,如果没有则创建。

关键代码:构造函数是私有的。

应用实例:

  • 1、一个班级只有一个班主任。

  • 2、Windows 是多进程多线程的,在操作一个文件的时候,就不可避免地出现多个进程或线程同时操作一个文件的现象,所以所有文件的处理必须通过唯一的实例来进行。

  • 3、一些设备管理器常常设计为单例模式,比如一个电脑有两台打印机,在输出的时候就要处理不能两台打印机打印同一个文件。

优点:

  • 1、在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例(比如管理学院首页页面缓存)。

  • 2、避免对资源的多重占用(比如写文件操作)。

缺点:没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化。

使用场景:

  • 1、要求生产唯一序列号。

  • 2、WEB 中的计数器,不用每次刷新都在数据库里加一次,用单例先缓存起来。

  • 3、创建的一个对象需要消耗的资源过多,比如 I/O 与数据库的连接等。

注意事项:getInstance() 方法中需要使用同步锁 synchronized (Singleton.class) 防止多线程同时进入造成 instance 被多次实例化。

实现:

懒汉式,线程安全

是否 Lazy 初始化:是

是否多线程安全:是

实现难度:易

描述:这种方式具备很好的 lazy loading,能够在多线程中很好的工作,但是,效率很低,99% 情况下不需要同步。 优点:第一次调用才初始化,避免内存浪费。 缺点:必须加锁 synchronized 才能保证单例,但加锁会影响效率。 getInstance() 的性能对应用程序不是很关键(该方法使用不太频繁)。

package bean;
//懒汉式
public class Dog {
    public static  Dog dog =null;
​
    private Dog(){
    }
    public static synchronized Dog getDog(){
        if (dog==null){
           dog =new Dog();
        }
        return dog;
    }
​
}

优点:
资源利用率高(第一次调用 getInstance() 方法时才进行对象实例化)

缺点:

    • 线程不安全(解决办法就是加锁 synchonized)

    • 第一次加载时不够快(多线程使用不必要的同步开销大)

 

饿汉式

是否 Lazy 初始化:否

是否多线程安全:是

实现难度:易

描述:这种方式比较常用,但容易产生垃圾对象。 优点:没有加锁,执行效率会提高。 缺点:类加载时就初始化,浪费内存。 它基于 classloader 机制避免了多线程的同步问题,不过,instance 在类装载时就实例化,虽然导致类装载的原因有很多种,在单例模式中大多数都是调用 getInstance 方法, 但是也不能确定有其他的方式(或者其他的静态方法)导致类装载,这时候初始化 instance 显然没有达到 lazy loading 的效果。


package bean;
//饿汉式
public class Dog {
    public static  Dog dog =new Dog();
    private Dog(){
    }
    public static synchronized Dog getDog(){
        return dog;
    }
​
}

优点

  • 线程安全(不需要线程同步)
  • 第一次调用时反应速度快(类加载即实例化对象)

缺点
资源利用率不高(无论是否使用都将占据内存空间)

总结

一般采用饿汉式(追求性能)

适用场景

  1. 需要频繁实例化然后销毁的对象

  2. 创建对象时耗时过多或者耗资源过多,但又经常用到的对象

  3. 有状态的工具类或管理类对象

  4. 频繁访问数据库或文件的对象

应用场景

  1. 网站的计数器

  2. 应用程序的日志应用

  3. Web 应用的配置对象的读取

  4. 数据库连接池的设计

  5. 多线程的线程池的设计

 
 

标签:设计模式,JAVA,对象,Dog,实例,线程,单例,多线程
From: https://www.cnblogs.com/jlwtj/p/17733080.html

相关文章

  • JAVA高级教程
    高级教程数据结构枚举一种从数据结构中取回连续元素的方式位集合可以单独设置和清楚的位或标志向量Vector是一个基于动态数组的集合类栈实现了一个后进先出的数据结构字典定义了键映射到值的数据结构哈希表在用户定义键结构的基础上来组织数据的手......
  • JavaScript——“==”和“===”区别(双等于号和三等于号区别)
    1.==:双等于号称为等值符。当等号两边为类型相同的值时,则直接比较值是否相同;当类型不同时,会先进行类型转换,转换为相同的类型后再进行比较。类型转化规则:1)当等号两边为boolean,string,number三者中任意两者进行对比时,会优先转换为number进行比较2)当等号两......
  • java程序,如何打印详细报错堆栈信息
    try{System.out.println(1/0);}catch(finalExceptione){log.error("ERROR","Errorfound:",e);log.error("ERROR","Errorfound:"+e.getMessage());log.error("ERROR","Errorfo......
  • Java-统计程序运行的时长(计算两个时间相差的秒数)
    最近在做Hbase的查询性能验证,需要统计查询的执行时长,所以需要统计开始时间和结束时间的时间差。下面是使用SimpleDateFormat和Date计算时间差(相差秒数)的程序示例,仅供参考。packagecom.sgcc;importjava.text.ParseException;importjava.text.SimpleDateFormat;importjav......
  • Java函数AI生成器:秒级体验,高质量生成
    职业使然,之前我自己试用并给小伙伴们推荐过不少大模型相关的产品,这些产品看起来牛逼plus,但是它们要么对国内有限制,要么是申请制/邀请制,自己没个资想搞个账号去体验一下都难如登天,忍不住吐槽某大厂虽然早早的对外宣布面向全民开发,但实际上提交了手机号码还在等待排队上车,掐指一算,有......
  • java实现文件上传与下载
    一、对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的,Servlet获取上传文件的输入流然后再解析里面的请求参数是比较麻烦。 JSP代码,POST请求,表单必须设置为enctype="multipart/form-data"<spanstyle="font-size:14px;"><formaction="upload3"method="po......
  • Java实现四则运算生成器
    这个作业属于哪个课程计科二班这个作业要求在哪里结对项目这个作业的目标熟悉结对编程项目成员龙新超3121004921github链接:龙新超github艾孜海尔江3121004900github链接:海尔江githubPSP表格PSP2.1PersonalSoftwareProcessStages预估耗时(分钟)实......
  • JavaScript下载base64位文件
    1/**2*下载文件3**/4functiondownloadExcel(base64Data){5varmyBlob=this.base64toBlob(base64Data);6varmyUrl=URL.createObjectURL(myBlob);7varlink=document.createElement("a");8......
  • Java内值传递和引用传递记录
    不管哪个语言都有值传递,引用传递两种方式,在C语言里面引用传递用指针搞定。在Java里面没有指针,所以Java就规定(之前的设计)了某些类型是值传递,某些是引用传递,我这里不想一个一个写下来了,浪费时间,现在查AI那么方便的事。写程序的人,必须要知道两个概念。因为知道才是现在最重要的,怎么......
  • Java泛型简明解析:易懂但全面的介绍
    引言Java泛型的背景和作用Java泛型是Java编程语言中的一个特性,引入泛型的目的是为了增强代码的类型安全性和重用性。在没有泛型之前,Java中的集合类(如ArrayList、HashMap等)只能存储Object类型的对象,这使得在使用集合时需要进行强制类型转换,容易出现类型错误。泛型的背景:在Java5版本......