精华内容
下载资源
问答
  • 文章目录一、什么单例模式二、应用场景三、优缺点四、代码样例总结 一、什么单例模式 单例模式是一种常用的软件设计模式,其定义是单例对象的类只能允许一个实例存在。 许多时候整个系统只需要拥有一个的全局...

    深入理解设计模式-双锁单例模式


    一、什么是单例模式

    单例模式是一种常用的软件设计模式,其定义是单例对象的类只能允许一个实例存在。
    许多时候整个系统只需要拥有一个的全局对象,这样有利于我们协调系统整体的行为。比如在某个服务器程序中,该服务器的配置信息存放在一个文件中,这些配置数据由一个单例对象统一读取,然后服务进程中的其他对象再通过这个单例对象获取这些配置信息。这种方式简化了在复杂环境下的配置管理。

    在这里插入图片描述


    二、应用场景

    举一个例子,网站的计数器,一般也是采用单例模式实现,如果你存在多个计数器,每一个用户的访问都刷新计数器的值,这样的话你的实计数的值是难以同步的。但是如果采用单例模式实现就不会存在这样的问题,而且还可以避免线程安全问题。同样多线程的线程池的设计一般也是采用单例模式,这是由于线程池需要方便对池中的线程进行控制 同样,对于一些应用程序的日志应用,或者web开发中读取配置文件都适合使用单例模式,如HttpApplication 就是单例的典型应用。 从上述的例子中我们可以总结出适合使用单例模式的场景和优缺点: 适用场景: 1.需要生成唯一序列的环境 2.需要频繁实例化然后销毁的对象。 3.创建对象时耗时过多或者耗资源过多,但又经常用到的对象。 4.方便资源相互通信的环境

    三、优缺点

    优点:
    1.在内存中只有一个对象,节省内存空间;
    2.避免频繁的创建销毁对象,可以提高性能;
    3.避免对共享资源的多重占用,简化访问;
    4.为整个系统提供一个全局访问点。
    缺点:
    1.不适用于变化频繁的对象;
    2.滥用单例将带来一些负面问题,如为了节省资源将数据库连接池对象设计为的单例类,可能会导致共 享连接池对象的程序过多而出现连接池溢出;
    4.如果实例化的对象长时间不被利用,系统会认为该对象是垃圾而被回收,这可能会导致对象状态的丢失;


    四、代码实现

    饿汉单例模式

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

    类加载的方式是按需加载,且加载一次。。因此,在上述单例类被加载时,就会实例化一个对象并交给自己的引用,供系统使用;而且,由于这个类在整个生命周期中只会被加载一次,因此只会创建一个实例,即能够充分保证单例,这种写法比较简单,就是在类装载的时候就完成实例化。避免了线程同步问题。

    懒汉单例模式

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

    我们从懒汉式单例可以看到,单例实例被延迟加载,即只有在真正使用的时候才会实例化一个对象并交给自己的引用。
    这种写法起到了Lazy Loading的效果,但是只能在单线程下使用。如果在多线程下,一个线程进入了if (singleton == null)判断语句块,还未来得及往下执行,另一个线程也通过了这个判断语句,这时便会产生多个实例。所以在多线程环境下不可使用这种方式。

    双锁单例模式

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

    双锁模式,进行了两次的判断,第一次是为了避免不要的实例,第二次是为了进行同步,避免多线程问题。由于singleton=new Singleton()对象的创建在JVM中可能会进行重排序,在多线程访问下存在风险,使用volatile修饰signleton实例变量有效,解决该问题。


    总结

    单例模式的实现方法还有很多。上述是比较经典的实现方式,也是我们应该掌握的几种实现方式。
    从这四种实现中,我们可以总结出,要想实现效率高的线程安全的单例,我们必须注意以下两点:
    1.尽量减少同步块的作用域;
    2.尽量使用细粒度的锁。

    展开全文
  • 单例模式 单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。 这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保...

    单例模式

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

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

    注意:

    • 1、单例类只能有一个实例。
    • 2、单例类必须自己创建自己的唯一实例。
    • 3、单例类必须给所有其他对象提供这一实例。

    介绍

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

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

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

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

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

    应用实例: 1、一个党只能有一个书记。 2、Windows 是多进程多线程的,在操作一个文件的时候,就不可避免地出现多个进程或线程同时操作一个文件的现象,所以所有文件的处理必须通过唯一的实例来进行。 3、一些设备管理器常常设计为单例模式,比如一个电脑有两台打印机,在输出的时候就要处理不能两台打印机打印同一个文件。

    优点: 1、在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例(比如管理学院首页页面缓存)。 2、避免对资源的多重占用(比如写文件操作)。

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

    使用场景: 1、要求生产唯一序列号。 2、WEB 中的计数器,不用每次刷新都在数据库里加一次,用单例先缓存起来。 3、创建的一个对象需要消耗的资源过多,比如 I/O 与数据库的连接等。

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

    为什么要用单例模式?

    public class Printer {
        private static Printer printer =null;//创建一个私有的全局变量
        /*
         * 如果有多线程并发访问时,上锁,让其排队等候,一次只能一人用。
         */
        public static synchronized Printer getPrinter(){
            if(printer==null){//如果为空,创建本实例
                printer = new Printer();
            }
            return printer;
        }
        /*
         * 构造私有化,保证在系统的使用中,只有一个实例
         */
        private Printer(){
            
        }
    }

    从代码上来分析,单例模式,首先向外提供了一个可被访问的实例化的对象,如果没有此对象时,该printer类创建一个。如果遇到多线程并发访问,加上关键字Synchronized,上锁让没有持有该对象的类处于等待状态。当前持有该printer的线程任务结束之后,处于等待中的线程才能逐个去持有该实例,去操作其方法。这样的一个过程 在编程中被称为单例模式。
    如果在系统中不使用单例模式的话,在碰到多线程访问的时候,printer就会给要请求的类,分别在内存中new出一个printer对象,让这些请求的类去做print方法。这样大量占有内存,就会导致系统运行变慢,像电脑的CPU一样,占有量极高,电脑卡死不动的感觉。因为系统的硬件设施需求变动量小,所以只能想出一个节约成本 的方法就是,单例模式,让多线程处于等待的状态,一个 一个的去解决,这样,即节约内存,提交了运行的成本。也就是单例存在的意义。

     

    展开全文
  • 序列化破环单例模式,实例代码如下: (1) 饿汉式单例模式,实现了序列化接口 public class SeriableSingleton implements Serializable{ private static final SeriableSingleton instance=new ...

    序列化破环单例模式,实例代码如下:

    (1) 饿汉式单例模式,实现了序列化接口

    public class SeriableSingleton implements Serializable{
        private static final SeriableSingleton instance=new SeriableSingleton();
        private SeriableSingleton(){}
        public static SeriableSingleton getInstance(){
            return instance;
        }
    }

    (2)  对单例模式进行序列化和反序列化破坏

    public class SeriableSingletonTest {
        public static void main(String[] args) {
            SeriableSingleton s1=null;
            SeriableSingleton s2=SeriableSingleton.getInstance();
            FileOutputStream fos=null;
            ObjectOutputStream oos=null;
            FileInputStream fis=null;
            ObjectInputStream ois=null;
    
            try {
                fos=new FileOutputStream("SeriableSingleton.obj");
                oos=new ObjectOutputStream(fos);
                oos.writeObject(s2);
                oos.flush();
                oos.close();
    
                fis=new FileInputStream("SeriableSingleton.obj");
                ois=new ObjectInputStream(fis);
                s1=(SeriableSingleton)ois.readObject();
                ois.close();
    
                System.out.println(s1);
                System.out.println(s2);
                System.out.println(s1==s2);
            } catch (Exception e) {
                e.printStackTrace();
            }
    
        }
    }

    此段代码执行结果如下:

    com.wxz.designpattern.singleton.SeriableSingleton@7ba4f24f
    com.wxz.designpattern.singleton.SeriableSingleton@6d6f6e28
    false

    由代码执行结果可看出,对单例模式执行完序列化和反序列化后,创建了新的对象,破坏了单例模式,违背了单例模式设计初衷。

    (3) 如何保证序列化方式下也能实现单例?

    解决方法很简单,只需要在单例类中增加readResolve()方法,代码如下:

    public class SeriableSingleton implements Serializable{
        private static final SeriableSingleton instance=new SeriableSingleton();
        private SeriableSingleton(){}
        public static SeriableSingleton getInstance(){
            return instance;
        }
        public Object readResolve(){
            return instance;
        }
    }

    再次执行SeriableSingletonTest测试方法,执行结果如下:

    com.wxz.designpattern.singleton.SeriableSingleton@6d6f6e28
    com.wxz.designpattern.singleton.SeriableSingleton@6d6f6e28
    true

    由此可见,增加readResolve()方法后解决了序列化方法对单例模式的破坏。

    展开全文
  • 单例模式中,遇到多线程总要考虑一个性能问题,下面的代码是double-checked locking设计实现单例模式。先判断,如果创建的对象是null,就改加同步锁,然后再判断。这样避免了多线程下的重复创建对象,也解决了...
    在单例模式中,遇到多线程总要考虑一个性能问题,下面的代码是double-checked locking设计实现单例模式。
    先判断,如果创建的对象是null,就改加同步锁,然后再判断。这样避免了多线程下的重复创建对象,也解决了
    整体加同步锁倒是性能的缺陷问题.在JDK 5之后,Java使用了新的内存模型。volatile关键字有了明确的语义。
    在JDK1.5之前,volatile是个关键字,但是并没有明确的规定其用途——被volatile修饰的写变量不能和
    之前的读写代码调整(控制内存),读变量不能和之后的读写代码调整!因此,只要我们简单的把instance加
    上volatile关键字就可以了。来源于论坛:http://bbs.csdn.net/topics/391840031
    public class SingletonClass { 
    
      private volatile static SingletonClass instance = null; 
    
      public static SingletonClass getInstance() { 
        if (instance == null) { 
          synchronized (SingletonClass.class) { 
            if (instance == null) { 
              instance = new SingletonClass(); 
            } 
          } 
        } 
        return instance; 
      } 
    
      private SingletonClass() { 
    
      } 
    
    }

    展开全文
  • 单例模式解决RabbitMQ超出最大连接问题
  • 使用反射对单例模式的破坏: /** * 反射破坏单例 */ public class ProxyBreakSingleton { @Test public void test(){ //通过单例模式创建对象 DoubleIfSynchronizedSingleton synchronizedSingleton = ...
  • 目录 最终解决方案 探讨为何这么写? 最终解决方案 双重检查加锁 首先检查是否实例已经创建了,如果尚未创建,才进行同步。这样一来,只有第一次会同步 ...public class ... //单例解决并发问题 if (sn
  • 其实如果想实现这种目的有很多方法,这里我之所以提及是因为我之前在使用单例模式的时候没有注意到我的单例模式代码还有提高效率的空间,接下来将把我之前实现单例模式的代码和通过改进的代码列举出来,通过对比指出...
  • * ToastUtils 利用单例模式解决重命名toast重复弹出的问题 */ public class ToastUtils { private static ToastUtils mToastUtils; private static Toast mToast; private ToastUtils(C
  • 由此我上网查了一下,在使用单例模式时,一定要注意线程安全问题,之前的写法没有任何问题。如下: package com.xhz.singleton; /** * 单例 * @author xhz */ public class Singleton {...
  • 解决懒汉单例模式线程安全问题 1, 懒汉单例模式 package SingleTonTest; /** * @Name: 懒汉单例设计模式 * @Author:ZYJ * @Date:2019-07-25-20:55 * @Description: */ class Singleton{ private static ...
  • 单例模式

    2019-10-30 18:26:34
    单例模式解决问题: 单例模式防止数据处理时发生冲突,解决资源共享操作等问题。 单例模式的两种方式: 1、懒汉模式 说得简单点懒汉模式就是需要用到时才创建(比较懒),如下图所示: 2、饿汉模式 饿汉模式就是...
  • 1 破坏单例模式 除枚举方式外,其它单例类(Singleton)可以创建多个对象。有两种方式可以破坏单例模式,分别是序列化和反射。 1.1 序列化反序列化 Singleton类: public class Singleton implements Serializable {...
  • 实现单例模式主要有如下几个关键点: 构造函数不对外开放,一般为private 通过一个静态方法或枚举返回单例类对象 确保单例类的对象有且只有一个,尤其是在多线程的环境下 确保单例类对象在反序列化时不会重新...
  • DCL单例模式,如何解决DCL问题

    千次阅读 2019-02-27 19:14:41
    何为DCL,DCL即Double Check Lock,...下面从几个单例模式来讲解 懒汉式 public void Singleton{ private static Singleton singleton; private Singleton(){} public static Singleton getInstance(){ if(...
  • 单例模式中分为懒汉式和饿汉式 其中,懒汉式是线程不安全的,当有多条线程同时访问单例对象时,则会出现多线程临界资源问题。 现在用多线程实现并解决线程安全问题 饿汉式 public class SigletonDemo01 { static ...
  •  2:spring单例模式的安全问题是使用ThreadLocal解决单例模式的意思就是只有一个实例。单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。这个类称为单例类。 当多用户同时请求...
  • 单例模式详解一、单例模式的定义及应用场景二、饿汉式单例模式(一)、饿汉式单例...ExcetorThread(2)、测试类:LazySimpleSingletonTest3、模拟线程安全问题原因分析(四)、懒汉式单例模式代码案例一的解决方法1
  • 单例模式的线程安全问题

    千次阅读 2019-06-23 22:14:21
    如果每一个请求进来我们对单独的实例化一个对象势必会极大损耗我们系统的性能,那么我们如何去解决多线程资源共享的问题——一起来了解一下设计模式中的单例模式吧!
  • 序列化破坏单例模式解决办法

    千次阅读 2019-01-04 02:43:22
    最近遇到一个问题单例模式可以序列化吗? 印象中单例模式的代码没有实现序列化接口的,可是究其原因却不知道为什么, 网上搜了下,然后自己也验证一下 。 单例模式 这里用了懒汉模式,同时实现序列化接口 /** ...
  • 单例模式什么

    千次阅读 2020-03-01 14:00:13
    什么要用单例模式? 单例模式节省公共资源,对应到我们计算机里面,像日志管理、打印机、数据库连接池、应用配置。 单例模式方便控制,就像日志管理,如果多个人同时来写日志,你一笔我一笔那整个日志文件都...
  • 单例模式——解决MDI子窗体实例化的问题

    千次阅读 热门讨论 2014-06-01 21:33:38
    机房收费系统进行有一段时间了,但是始终有些历史遗留问题。比如,如何MDI子窗体如何显示在上层的问题和MDI子窗体实例化的问题。  对于如何显示在上层的问题,我这次采用的还是SetParent函数,在模块里面添加: ...
  • 什么单例设计模式?  解决问题:可以保证一个类在内存中的对象唯一性,必须对于多个程序使用同一个配置信息对象时,就需要保证该对象的唯一性。     如何保证?  1、不允许其他程序用new创建该类的对象...
  • Python 中的单例模式单例模式单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在。当你希望在整个系统中,某个类只能出现一个实例时,单例对象就能派上用场。...
  • C++ 单例模式

    万次阅读 2021-04-21 00:05:19
    原创文章,转载请注明出处。 本文主要单例的用处以及问题所做介绍

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 133,979
精华内容 53,591
关键字:

单例模式主要解决什么问题