一、到底什么是单例,多例?
-
通俗解释:
- 你用杯子喝可乐,喝完了不刷,继续去倒果汁喝,就是单例。
- 你用杯子喝可乐,直接扔了杯子,换个杯子去倒果汁喝,就是多例。
- 数据库连接池就是单例模式,有且仅有一个连接池管理者,管理多个连接池对象。
-
单例和多例的区别:
-
什么是单例多例:
所谓单例就是所有的请求都用一个对象来处理,比如我们常用的service和dao层的对象通常都是单例的,而多例则指每个请求用一个新的对象来处理,比如action; -
如何产生单例多例:
在通用的SSH中,单例在spring中是默认的,如果要产生多例,则在配置文件的bean中添加scope=“prototype”; -
为什么用单例多例:
- 之所以用单例,是因为没必要每个请求都新建一个对象,这样子既浪费CPU又浪费内存;
- 之所以用多例,是为了防止并发问题;即一个请求改变了对象的状态,此时对象又处理另一个请求,而之前请求对对象状态的改变导致了对象对另一个请求做了错误的处理;
-
何时用单例?何时用多例?
- 当对象含有可改变的状态时(更精确的说就是在实际应用中该状态会改变),则多例,否则单例;
- 单例在内存中该对象只有一个内存对应地址。无论你多少个线程访问那个对象,都是同一个地址。这样节省内存。如果希望节省内存,则使用单例。
二、单例模式有以下特点:
- 单例类只能有一个实例。
- 单例类必须自己创建自己的唯一实例。
- 单例类必须给所有其他对象提供这一实例。
- 单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。
- 在计算机系统中,线程池、缓存、日志对象、对话框、打印机、显卡的驱动程序对象常被设计成单例。这些应用都或多或少具有资源管理器的功能。每台计算机可以有若干个打印机,但只能有一个Printer Spooler,以避免两个打印作业同时输出到打印机中。每台计算机可以有若干通信端口,系统应当集中管理这些通信端口,以避免一个通信端口同时被两个请求同时调用。总之,选择单例模式就是为了避免不一致状态,避免政出多头。
三、懒汉式单例和饿汉式单例区别:
-
直观区别:
- 饿汉:饿汉就是类一旦加载,就把单例初始化完成,保证getInstance的时候,单例是已经存在了。
- 懒汉:懒汉比较懒,只有当调用getInstance的时候,才回去初始化这个单例。
-
从性能线程上的区别:
四、什么是线程安全?
-
如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。
-
或者说:一个类或者程序所提供的接口对于线程来说是原子操作,或者多个线程之间的切换不会导致该接口的执行结果存在二义性,也就是说我们不用考虑同步的问题,那就是线程安全的。
五、结论:
-
由结果可以得知单例模式为一个面向对象的应用程序提供了对象惟一的访问点,不管它实现何种功能,整个应用程序都会同享一个实例对象。
-
单例模式中懒汉式本身是非线程安全的。饿汉式是线程安全的,可以直接用于多线程而不会出现问题。
-
当对象含有可改变的状态时,则多例,否则单例。
-
单例对内存占用更小。