单例与多例对比

2024-05-24 11:58
文章标签 单例 对比 多例

本文主要是介绍单例与多例对比,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

单例多例需要搞明白两个问题:

  1. 什么是单例多例;

  2. 如何产生单例多例;

  3. 为什么要用单例多例

  4. 什么时候用单例,什么时候用多例;

  5. 什么是单例、多例:
    所谓单例就是所有的请求都用一个对象来处理,比如我们常用的service和dao层的对象通常都是单例的,而多例则指每个请求用一个新的对象来处理,比如action;

一、单例模式和多例模式说明:

1.单例模式和多例模式属于对象模式。

2.单例模式的对象在整个系统中只有一份,多例模式可以有多个实例。

3.它们都不对外提供构造方法,即构造方法都为私有。

二、应用举例

1.单例模式举例:

第一种:懒汉式(线程不安全,加上synchronized后线程安全)

public class Singleton {private static Singleton instance;private Singleton (){}public static synchronized  Singleton getInstance() {if (instance == null) {instance = new Singleton();}return instance;}
}

第二种:饿汉式(线程安全)

public class Singleton {private static Singleton instance = new Singleton();private Singleton (){}public static Singleton getInstance() {return instance;}
}

这种方式基于classloder机制避免了多线程的同步问题,不过,instance在类装载时就实例化,虽然导致类装载的原因有很多种,在单例模式中大多数都是调用getInstance方法, 但是也不能确定有其他的方式(或者其他的静态方法)导致类装载,这时候初始化instance显然没有达到lazy loading的效果。

复制代码
public class Singleton {
private Singleton instance = null;
static {
instance = new Singleton();
}
private Singleton (){}
public static Singleton getInstance() {
return this.instance;
}
}
复制代码
表面上看起来差别挺大,其实差不多,都是在类初始化即实例化instance。

第三种:静态内部类

public class Singleton {private static class SingletonHolder {private static final Singleton INSTANCE = new Singleton();}private Singleton (){}public static final Singleton getInstance() {return SingletonHolder.INSTANCE;}
}

这种方式同样利用了classloder的机制来保证初始化instance时只有一个线程,它跟饿汉式不同的是(很细微的差别):饿汉式是只要Singleton类被装载了,那么instance就会被实例化(没有达到lazy loading效果),而这种方式是Singleton类被装载了,instance不一定被初始化。因为SingletonHolder类没有被主动使用,只有显示通过调用getInstance方法时,才会显示装载SingletonHolder类,从而实例化instance。想象一下,如果实例化instance很消耗资源,我想让他延迟加载,另外一方面,我不希望在Singleton类加载时就实例化,因为我不能确保Singleton类还可能在其他的地方被主动使用从而被加载,那么这个时候实例化instance显然是不合适的。这个时候,这种方式相比饿汉式就显得很合理。

第四种:枚举

public enum Singleton {INSTANCE;public void whateverMethod() {}
}

这种方式是Java作者提倡的方式,它不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象,可谓是很坚强的壁垒啊,不过,个人认为由于1.5中才加入enum特性,用这种方式写不免让人感觉生疏,在实际工作中,我也很少看见有人这么写过。

public enum EnumTest {MON, TUE, WED, THU, FRI, SAT, SUN;
}public class Test{public static void main(String[] args) {for (EnumTest e : EnumTest.values()) {System.out.println(e.toString());}System.out.println("----------------我是分隔线------------------");EnumTest test = EnumTest.MON;switch (test) {case MON:System.out.println("今天是星期一");break;case TUE:System.out.println("今天是星期二");break;// ... ...default:System.out.println(test);break;}}
}

打印结果

MON

TUE
WED
THU
FRI
SAT
SUN
----------------我是分隔线------------------
今天是星期一

第五种:双重校验锁

public class Singleton {private volatile static Singleton singleton;private Singleton (){}public static Singleton getSingleton() {if (singleton == null) {synchronized (Singleton.class) {if (singleton == null) {singleton = new Singleton();}}}return singleton;}
}

这个是第一种方式的升级版,俗称双重检查锁定。在JDK1.5之后,双重检查锁定才能够正常达到单例效果。

  1. 多例模式举例:

    import java.text.;
    import java.util.
    ;
    class NumberFormatTest
    {
    public static void displayNumber(Double d,Locale l)
    {
    NumberFormat nf;
    String dOut;
    nf = NumberFormat.getNumberInstance(l);
    dOut = nf.format(d);
    System.out.println(dOut + " " + l.toString());
    }
    public static void main(String[] args)
    {
    displayNumber(1234567.89,new Locale(“en”,“US”));
    displayNumber(1234567.89,new Locale(“de”,“DE”));
    displayNumber(1234567.89,new Locale(“fr”,“FR”));
    displayNumber(1234567.89,new Locale(“zh”,“CN”));
    }
    }

一个根据语言代码和地区代码格式化数字的多例模式例子

  1. 如何产生单例、多例:
    在通用的SSH中,单例在spring中是默认的,如果要产生多例,则在配置文件的bean中添加scope=“prototype”;

我就告诉你昨天我得问题你估计就明白了

我没用scope="prototype"就出现上面得验证问题了 连续点提交就这样
我添加后 不论怎么点都只会出现一个验证提示
3. 为什么用单例、多例:
之所以用单例,是因为没必要每个请求都新建一个对象,这样子既浪费CPU又浪费内存;
之所以用多例,是为了防止并发问题;即一个请求改变了对象的状态,此时对象又处理另一个请求,而之前请求对对象状态的改变导致了对象对另一个请求做了错误的处理;
用单例和多例的标准只有一个:
当对象含有可改变的状态时(更精确的说就是在实际应用中该状态会改变),则多例,否则单例;
4. 何时用单例?何时用多例?
对于struts2来说,action必须用多例,因为action本身含有请求参数的值,即可改变的状态;
而对于STRUTS1来说,action则可用单例,因为请求参数的值是放在actionForm中,而非action中的;
另外要说一下,并不是说service或dao一定是单例,标准同第3点所讲的,就曾见过有的service中也包含了可改变的状态,同时执行方法也依赖该状态,但一样用的单例,这样就会出现隐藏的BUG,而并发的BUG通常很难重现和查找;

原网址出自:http://www.cnblogs.com/zhangliang88/p/5388472.html
单例模式:http://cantellow.iteye.com/blog/838473

这篇关于单例与多例对比的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/998346

相关文章

在JS中的设计模式的单例模式、策略模式、代理模式、原型模式浅讲

1. 单例模式(Singleton Pattern) 确保一个类只有一个实例,并提供一个全局访问点。 示例代码: class Singleton {constructor() {if (Singleton.instance) {return Singleton.instance;}Singleton.instance = this;this.data = [];}addData(value)

免费也能高质量!2024年免费录屏软件深度对比评测

我公司因为客户覆盖面广的原因经常会开远程会议,有时候说的内容比较广需要引用多份的数据,我记录起来有一定难度,所以一般都用录屏工具来记录会议内容。这次我们来一起探索有什么免费录屏工具可以提高我们的工作效率吧。 1.福晰录屏大师 链接直达:https://www.foxitsoftware.cn/REC/  录屏软件录屏功能就是本职,这款录屏工具在录屏模式上提供了多种选项,可以选择屏幕录制、窗口

使用Spring Boot集成Spring Data JPA和单例模式构建库存管理系统

引言 在企业级应用开发中,数据库操作是非常重要的一环。Spring Data JPA提供了一种简化的方式来进行数据库交互,它使得开发者无需编写复杂的JPA代码就可以完成常见的CRUD操作。此外,设计模式如单例模式可以帮助我们更好地管理和控制对象的创建过程,从而提高系统的性能和可维护性。本文将展示如何结合Spring Boot、Spring Data JPA以及单例模式来构建一个基本的库存管理系统

类的load方法和initialize方法对比

1. load方法在main()之前被调用,而initialize方法在main()之后调用 load方法实际是在load_images过程中被调用的。load_images会将当前应用依赖的所有镜像(动态库)加载到内存,在在加载中首先是对镜像进行扫描,将所有包含 load 方法的类加入列表 loadable_classes ,然后从这个列表中逐一调用其所包含的 load 方法。 +[XXCl

C#设计模式(1)——单例模式(讲解非常清楚)

一、引言 最近在学设计模式的一些内容,主要的参考书籍是《Head First 设计模式》,同时在学习过程中也查看了很多博客园中关于设计模式的一些文章的,在这里记录下我的一些学习笔记,一是为了帮助我更深入地理解设计模式,二同时可以给一些初学设计模式的朋友一些参考。首先我介绍的是设计模式中比较简单的一个模式——单例模式(因为这里只牵涉到一个类) 二、单例模式的介绍 说到单例模式,大家第一

JavaScript正则表达式六大利器:`test`、`exec`、`match`、`matchAll`、`search`与`replace`详解及对比

在JavaScript中,正则表达式(Regular Expression)是一种用于文本搜索、替换、匹配和验证的强大工具。本文将深入解析与正则表达式相关的几个主要执行方法:test、exec、match、matchAll、search和replace,并对它们进行对比,帮助开发者更好地理解这些方法的使用场景和差异。 正则表达式基础 在深入解析方法之前,先简要回顾一下正则表达式的基础知识。正则

【HarmonyOS】-TaskPool和Worker的对比实践

ArkTS提供了TaskPool与Worker两种多线程并发方案,下面我们将从其工作原理、使用效果对比两种方案的差异,进而选择适用于ArkTS图片编辑场景的并发方案。 TaskPool与Worker工作原理 TaskPool与Worker两种多线程并发能力均是基于 Actor并发模型实现的。Worker主、子线程通过收发消息进行通信;TaskPool基于Worker做了更多场景化的功能封装,例

一些数学经验总结——关于将原一元二次函数增加一些限制条件后最优结果的对比(主要针对公平关切相关的建模)

1.没有分段的情况 原函数为一元二次凹函数(开口向下),如下: 因为要使得其存在正解,必须满足,那么。 上述函数的最优结果为:,。 对应的mathematica代码如下: Clear["Global`*"]f0[x_, a_, b_, c_, d_] := (a*x - b)*(d - c*x);(*(b c+a d)/(2 a c)*)Maximize[{f0[x, a, b,

claude和chatgpt对比:哪一个更适合你?

前言 我们都知道,Claude和ChatGPT都是当前人工智能领域中备受关注的对话生成模型,作为国外AI模型两大巨头,好像他们的实力都不相上下呀! 这时就会有很多同学疑惑,那我如果想选择AI,到底是选择Claude,还是ChatGPT呢?哪个更好呢?他们之间有什么不同独特的地方呢?他们又分别适合在哪些场景使用呢? 技术背景 Claude是由Anthropic公司开发的高性能模型,而Chat

单例模式以及反射对单例模式的破坏及防御

单例模式(Singleton Pattern)是一种确保类在应用程序生命周期内只存在一个实例的设计模式。它不仅提供了全局访问点,还能节省内存、控制实例的生命周期。但常见的单例模式实现方式如饿汉式、懒汉式、双重校验锁、静态内部类等,虽然设计良好,但都容易被 Java 的反射机制所破坏。本文将介绍这些单例实现方式的优缺点、反射如何破坏它们的唯一性,以及如何防御这种破坏。 1. 单例模式的常见实现