单例模式

最全的单例模式实现及各实现方式比较

佐手、 提交于 2019-12-09 13:39:53
单例模式算是 设计模式 中最容易理解,也是最容易手写代码的模式了吧。但是其中的坑却不少,所以也常作为面试题来考。本文主要对几种单例写法的整理,并分析其优缺点。很多都是一些老生常谈的问题,但如果你不知道如何创建一个线程安全的单例,不知道什么是双检锁,那这篇文章可能会帮助到你。 懒汉式,线程不安全 当被问到要实现一个单例模式时,很多人的第一反应是写出如下的代码,包括教科书上也是这样教我们的。 1 2 3 4 5 6 7 8 9 10 11 public class Singleton { private static Singleton instance; private Singleton (){} public static Singleton getInstance() { if (instance == null ) { instance = new Singleton(); } return instance; } } 这段代码简单明了,而且使用了懒加载模式,但是却存在致命的问题。当有多个线程并行调用 getInstance() 的时候,就会创建多个实例。也就是说在多线程下不能正常工作。 懒汉式,线程安全 为了解决上面的问题,最简单的方法是将整个 getInstance() 方法设为同步(synchronized)。 1 2 3 4 5 6 public static

如何正确地写出单例模式

こ雲淡風輕ζ 提交于 2019-12-09 13:39:33
单例模式算是设计模式中最容易理解,也是最容易手写代码的模式了吧。但是其中的坑却不少,所以也常作为面试题来考。本文主要对几种单例写法的整理,并分析其优缺点。很多都是一些老生常谈的问题,但如果你不知道如何创建一个线程安全的单例,不知道什么是双检锁,那这篇文章可能会帮助到你。 懒汉式,线程不安全 当被问到要实现一个单例模式时,很多人的第一反应是写出如下的代码,包括教科书上也是这样教我们的。 public class Singleton { private static Singleton instance; private Singleton (){} public static Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } } 这段代码简单明了,而且使用了懒加载模式,但是却存在致命的问题。当有多个线程并行调用 getInstance() 的时候,就会创建多个实例。也就是说在多线程下不能正常工作。 懒汉式,线程安全 为了解决上面的问题,最简单的方法是将整个 getInstance() 方法设为同步(synchronized)。 public static synchronized Singleton getInstance() { if

java高级工程师面试问题集结号(two)

时光总嘲笑我的痴心妄想 提交于 2019-12-09 12:11:53
###单例模式的优缺点 实现要点 Singleton模式是限制而不是改进类的创建。 Singleton类中的实例构造器可以设置为Protected以允许子类派生。 Singleton模式一般不要支持Icloneable接口,因为这可能导致多个对象实例,与Singleton模式的初衷违背。 Singleton模式一般不要支持序列化,这也有可能导致多个对象实例,这也与Singleton模式的初衷违背。 Singleton只考虑了对象创建的管理,没有考虑到销毁的管理,就支持垃圾回收的平台和对象的开销来讲,我们一般没必要对其销毁进行特殊的管理。 理解和扩展Singleton模式的核心是“如何控制用户使用new对一个类的构造器的任意调用”。 可以很简单的修改一个Singleton,使它有少数几个实例,这样做是允许的而且是有意义的。 优点 实例控制:Singleton 会阻止其他对象实例化其自己的 Singleton 对象的副本,从而确保所有对象都访问唯一实例 灵活性:因为类控制了实例化过程,所以类可以更加灵活修改实例化过程 缺点 开销:虽然数量很少,但如果每次对象请求引用时都要检查是否存在类的实例,将仍然需要一些开销。可以通过使用静态初始化解决此问题,上面的五种实现方式中已经说过了。 可能的开发混淆:使用 singleton 对象(尤其在类库中定义的对象)时,开发人员必须记住自己不能使用

设计模式学习笔记之单例模式

我的未来我决定 提交于 2019-12-08 23:13:31
什么是单例模式? 顾名思义,就是只有一个实例,也就是说一个应用程序中只有一个实例对象. 既然一个系统,一个应用程序中只有一个实例,那么也就说明了如果操作这一个对象,必然涉及到共享资源,涉及到资源分配问题,资源竞争等问题. 那么我们的应用场景是什么呢? 1. 网站的在线人数. 网站的在线人数在某一个时刻,所有人看到的是一样的, 是这个网站这个时刻,所有用户所共享的. 2. 池化技术. 比如数据库的连接池. 每个数据库的可支持的连接数量是有限,而且连接对象创建和销毁也是比较耗内存的. 通过一个统一的入口去控制,可以保证对数据库的压力在可控的范围内,同是也可以保证出具库连接的持续使用. 3. 配置中心. 一个应用程序针对通过一个配置文件的加载只需要加载一次即可,不需要多次加载. 其实以上只是一些常见的应用场景,当然单例模式的应用场景也远不止于此. 本文参考的博客地址为: https://www.cnblogs.com/mr-yang-localhost/p/9644417.html 参考的博客的写的很不错, 如果想了解更多,可以去看看这篇参考的博客 接下来我们来看一下常见的实现方式,以及其中的对比. 饿汉式,即直接初始化好,使用的时候直接调用即可. package com.cbl.design.singletondesign; public class HungrySingleton {

案例分析:设计模式与代码的结构特性

天大地大妈咪最大 提交于 2019-12-08 20:22:27
软件设计模式(Design pattern),又称设计模式,是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性、程序的重用性。 单例模式定义    单例模式,是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中,应用该模式的类一个类只有一个实例。即一个类只有一个对象实例。要实现这一点,可以从客户端对其进行实例化开始。因此需要用一种只允许生成对象类的唯一实例的机制,"阻止"所有想要生成对象的访问。使用工厂方法来限制实例化过程。这个方法应该是静态方法(类方法),因为让类的实例去生成另一个唯一实例毫无意义。 单例模式的动机   对于系统中的某些类来说,只有一个实例很重要,例如,一个系统中可以存在多个打印任务,但是只能有一个正在工作的任务;一个系统只能有一个窗口管理器或文件系统;一个系统只能有一个计时工具或ID(序号)生成器。如在Windows中就只能打开一个任务管理器。如果不使用机制对窗口对象进行唯一化,将弹出多个窗口,如果这些窗口显示的内容完全一致,则是重复对象,浪费内存资源;如果这些窗口显示的内容不一致,则意味着在某一瞬间系统有多个状态,与实际不符,也会给用户带来误解,不知道哪一个才是真实的状态

单例模式

为君一笑 提交于 2019-12-08 10:14:25
package com.company.java.oop.instance; /** * 如何设计,才能保证如下类的实例对象 * 在内存中只有一份? * 1)让外界从一个池中去取对象(通过池保证类的实例在池中一份) * 2)让外界直接通过类的静态方法获取类内部创建的一个实例。 */ class Singleton01{//应用场景:小对象 static Singleton01 instance=new Singleton01(); private Singleton01() {} public static Singleton01 getInstance() { return instance; } } class Singleton02{//适合场景:大对象,单线程 private Singleton02() { System.out.println("Singleton02()"); } private static Singleton02 instance; /** * 线程不安全?导致线程不安全的原因是什么? * 1)多个线程并发执行 * 2)多个线程有共享数据集(例如instance) * 3)多个线程在共享数据上的操作不是原子操作。 * @return */ public static Singleton02 getInstance() { if(instance=

servlet不是线程安全的

半世苍凉 提交于 2019-12-08 09:46:30
在tomcat容器中,servlet默认是单例模式;如果实现ISingleThreadModule标记接口 则针对多个请求创建多个实例(最多20个),为了实现线程安全,可以: 1.使用局部变量 而不是实例变量 2.使用synchronized关键字 综上说明静态变量、实例变量、局部变量,三者使用范围或者说生命周期越大 则越不线程安全 来源: https://www.cnblogs.com/hzq3554055/p/12004630.html

《Java-单例模式》

人走茶凉 提交于 2019-12-07 13:52:02
单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。在计算机系统中,线程池、缓存、日志对象、对话框、打印机、显卡的驱动程序对象常被设计成单例。这些应用都或多或少具有资源管理器的功能。每台计算机可以有若干个打印机,但只能有一个Printer Spooler,以避免两个打印作业同时输出到打印机中。每台计算机可以有若干通信端口,系统应当集中管理这些通信端口,以避免一个通信端口同时被两个请求同时调用。总之,选择单例模式就是为了避免不一致状态,避免政出多头。 那就让我们看看几种常见的单例模式吧。 //懒汉式单例类.在第一次调用的时候实例化自己 public class Singleton { private Singleton() {} private static Singleton single=null; //静态工厂方法 public static Singleton getInstance() { if (single == null) { single = new Singleton(); } return single; } } 应该是大家写的比较多的了,但是这种写法的时候在多线程的时候就会出现问题,于是就引出了下面两种写法 1、在getInstance方法上加同步 public static synchronized Singleton

如何防止单例模式被JAVA反射攻击

試著忘記壹切 提交于 2019-12-07 13:51:49
单例模式相信大家都知道,用过的人不在少数。之前写过一篇博文《singleton模式四种线程安全的实现》(参见:http://blog.csdn.NET/u013256816/article/details/50427061),讲诉了单例模式的四种写法,并指出占位符模式的写法比较ok,详见如下: package com.effective.singleton; public class Elvis { private static boolean flag = false; private Elvis(){ } private static class SingletonHolder{ private static final Elvis INSTANCE = new Elvis(); } public static Elvis getInstance() { return SingletonHolder.INSTANCE; } public void doSomethingElse() { } } 但这都是基于一个条件:确保不会通过反射机制调用私有的构造器。 这里举个例子,通过JAVA的反射机制来“攻击”单例模式: package com.effective.singleton; import java.lang.reflect.Constructor; import java

单例设计模式

吃可爱长大的小学妹 提交于 2019-12-07 09:53:54
对所有的Java开发者而言,所有项目中最为常见的三个设计模式:工厂设计模式、代理设计模式、单例设计模式。 单例设计模式: 如果一个类中定义有普通方法,那么这些普通方法一定要通过本类的实例化对象你才可以调用。 传统调用: class Single{ public void print(){ System.out.println("单身"); }}class TestDemo{ public static void main(String arg[]){ Single single = new Single(); single.print(); }}运行结果:单身 在本程序中Single是一个普通的类,由于本类并没有进行任何构造方法的定义,所以这个类中会自动生成一个无参的、什么都不做的的构造方法,正是因为如此,我们可以在外部进行无参构造的调用。 但现在相对Single 类做一个修改: class Single{ private Single(){} public void print(){ System.out.println("单身"); }}class TestDemo{ public static void main(String arg[]){ Single single= null; single = new Single(); single.print(); }} 运行结果