1 单例模式的使用场景

(1)当创建一个对象所占用的资源很多,但同时又需要使用到该对象

(2)当堆系统内的资源要求统一读写时,比如读写的配置信息,此时必须要求创建的实例信息相同

(3)当有多个实例可能会引起程序逻辑错误时

总结:单例模式适用于只需要创建一个实例对象,程序全部使用同一个实例对象

2 实现方法

根据使用场景提炼出要点:

(1)某个类只能有一个实例

(2)必须要自行创建实例

(3)必须向整个系统提供这个实例

实现方法:

(1)只提供私有的构造方法

(2)含有一个该类的静态私有对象

(3)要提供一个静态的公用方法用于获取、创建私有对象

根据上面的描述,提供了两种实现单例模式的方法分别为饿汉式和懒汉式

3 饿汉式

该模式在创建类的时候就实例化,这样在获取的时候就可以有很快的效率但因为该类的实例化对象一直存在,所以占用的空间还是比较大的

//饿汉式:创建对象实例的时候直接初始化  空间换时间
public class SingletonOne {
//1、创建类中私有构造
private SingletonOne(){ } //2、创建该类型的私有静态实例
private static SingletonOne instance = new SingletonOne(); //3、创建公有静态方法返回静态实例对象
public static SingletonOne getInstance(){
return instance;
}
}

在使用时可以采用: SingletonOne one =SingletonOne.getInstance(); 获取实例对象

4 懒汉式

与饿汉模式不同,是在第一次要使用该对象实例时才进行初始化,创建对象实例,这样第一使用时会花费时间,但节省了大量空间

//懒汉式:类内实例对象创建时并不直接初始化,直到第一次调用get方法时,才完成初始化操作
//时间换空间
public class SingletonTwo {
//1、创建私有构造方法
private SingletonTwo(){ } //2、创建静态的该类实例对象
private static SingletonTwo instance=null; //3、创建开放的静态方法提供实例对象
public static SingletonTwo getInstance(){
if(instance==null)
instance=new SingletonTwo(); return instance;
}
}

注:

懒汉式在多线程时可能会创建出多个多个对象,一个简单的方法就是加锁:

//懒汉式:类内实例对象创建时并不直接初始化,直到第一次调用get方法时,才完成初始化操作
//时间换空间
public class SingletonTwo {
//1、创建私有构造方法
private SingletonTwo(){ } //2、创建静态的该类实例对象
private static SingletonTwo instance=null; //3、创建开放的静态方法提供实例对象
public synchronized static SingletonTwo getInstance(){
if(instance==null)
instance=new SingletonTwo(); return instance;
}
}

在三步时加上了synchronized关键字,但当有static关键字时锁定其实是整个类而不是这个方法,这样锁的范围就太大了并且上锁开锁也比较消耗时间,因此有一种更为简便的方法:双重检查

public class LazyDoubleCheckSingleton {

    private static LazyDoubleCheckSingleton lazyDoubleCheckSingleton = null;

    private LazyDoubleCheckSingleton(){

    }
public static LazyDoubleCheckSingleton getInstance(){
if(lazyDoubleCheckSingleton == null){
//这个锁的范围和在static上一样的,但因为有了一个判断因此可以提高效率
synchronized (LazyDoubleCheckSingleton.class){
if(lazyDoubleCheckSingleton == null){
lazyDoubleCheckSingleton = new LazyDoubleCheckSingleton();
}
}
}
return lazyDoubleCheckSingleton;
}
}

上面的代码只是简单的优化,但又会引出一个新的问题:重排序:在单线程中一般情况下new一个对象在上面代码中即new LazyDoubleCheckSingleton();

是按照1 2 3 4 的步骤进行的,但有时2 3 的顺序也会互换这样可以提高效率,但是这样在多线程中就会遇到麻烦。

下图是上面代码中多线程的例子:

当线程0重排序时此时线程1会判断不为空,那么线程1便会访问对象,当对象此时还没有初始化因此便会报错。

解决方法1:禁止重排序,只需要在声明对象时加上一个关键字:volatile

private volatile static LazyDoubleCheckSingleton lazyDoubleCheckSingleton = null;

解决方法2:允许重排序,但不允许其他线程看到重排序

public class StaticInnerClassSingleton {

    //私有构造方法
private StaticInnerClassSingleton(){ } //对于静态内部类Jvm有一个初始化锁
private static class InnerClass{
private static StaticInnerClassSingleton staticInnerClassSingleton = new StaticInnerClassSingleton();
} public static StaticInnerClassSingleton getInstance(){
return InnerClass.staticInnerClassSingleton;
} }

5 单例模式的优缺点

优点:

(1)在内存中只有一个对象节省了内存空间

(2)避免了频繁的创建销毁对象,提高了性能

(3)避免对共享资源的多重占用

缺点:

(1)后期扩展比较困难

(2)如果实例化后的对象长期不利用,系统将默认为垃圾进行回收,造成对象状态丢失

6 序列化

这些部分还没有看,因为涉及到的知识大多不会。

7 注解

0

单例模式(Singleton)---创建型的更多相关文章

  1. 设计模式01: Singleton 单例模式(创建型模式)

    Singleton 单例模式(创建型模式) 动机(Motivation)当进行软件开发是会有这样一种需求:在系统中只有存在一个实例才能确保它们的逻辑正确性.以及良好的效率.这应该是类设计者的责任,而不 ...

  2. 设计模式学习之单例模式(Singleton,创建型模式)(4)

    假如程序中有一个Person类,我的需求就是需要在整个应用程序中只能new一个Person,而且这个Person实例在应用程序中进行共享,那么我们该如何实现呢? 第一步: 新建一个Person类,类中 ...

  3. Java设计模式 - 单例模式(创建型模式)

    单例模式我在上学期看一些资料时候学习过,没想到这学期的软件体系结构就有设计模式学习,不过看似篇幅不大,介绍得比较简单,在这里我总结下单例模式,一来整理之前的笔记,二来也算是预习复习课程了. 概述 单例 ...

  4. Java设计模式——单例模式(创建型模式)

    概述   单例模式保证对于每一个类加载器,一个类仅有一个实例并且提供全局的访问.其是一种对象创建型模式.对于单例模式主要适用以下几个场景: 系统只需要一个实例对象,如提供一个唯一的序列号生成器 客户调 ...

  5. Java设计模式03:常用设计模式之单例模式(创建型模式)

    1.  Java之单例模式(Singleton Pattern ) 单例模式是一种常见的设计模式,单例模式分三种:懒汉式单例.饿汉式单例.登记式单例三种. 单例模式有一下特点: 1.单例类只能有一个实 ...

  6. 设计模式 笔记 单例模式 Singleton

    //---------------------------15/04/09---------------------------- //Singleton 单例模式-----对象创建型模式 /* 1: ...

  7. C#设计模式之一单例模式(Singleton Pattern)【创建型】

    一.引言     看了李建忠老师的讲的设计模式已经有一段时间了(这段时间大概有一年多了),自己还没有写过自己的.有关设计模式的文章.这次想写一些关于设计模式的文章,用自己的理解和代码来写,算是复习一遍 ...

  8. 设计模式01 创建型模式 - 单例模式(Singleton Pattern)

    参考 [1] 设计模式之:创建型设计模式(6种) | 博客园 [2] 单例模式的八种写法比较 | 博客园 单例模式(Singleton  Pattern) 确保一个类有且仅有一个实例,并且为客户提供一 ...

  9. Python设计模式 - 创建型 - 单例模式(Singleton) - 十种

    对于很多开发人员来说,单例模式算是比较简单常用.也是最早接触的设计模式了,仔细研究起来单例模式似乎又不像看起来那么简单.我们知道单例模式适用于提供全局唯一访问点,频繁需要创建及销毁对象等场合,的确方便 ...

  10. 单例模式——创建型模式01

    1. 名称     单例模式(Singleton Pattern):确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类.单例模式是一种对象创建型模式. 2. 问题    ...

随机推荐

  1. Hadoop学习(2)-java客户端操作hdfs及secondarynode作用

    首先要在windows下解压一个windows版本的hadoop 然后在配置他的环境变量,同时要把hadoop的share目录下的hadoop下的相关jar包拷贝到esclipe 然后Build Pa ...

  2. 【转载】SpringBoot-配置发送邮件遇到的一些问题

    前言:前一天调用163邮箱发送邮件还么有问题,今天再调用就各种发送不成功,害的我都关闭授权,还花了一毛钱短信费重新开启授权,最后百度到了一篇文章,非常贴切,在此转载下. 本人遇到的错误代码是554,邮 ...

  3. mysql innodb数据库损坏导致无法启动

    生产环境中的mysql突然启动不了,查了原因是innodb库错误,以前就遇到过这个问题,稀里糊涂的没解决,结果导致大量数据丢失.这些又遇到这个问题,果断把那个有问题的数据库移动了别的地方,启动了mys ...

  4. 【数据结构】P1996 约瑟夫问题

    [题目链接] https://www.luogu.org/problem/P1996 题目描述 n个人(n<=100)围成一圈,从第一个人开始报数,数到m的人出列,再由下一个人重新从1开始报数, ...

  5. 【思维】ABC

    题目描述 You are given a string s consisting of A, B and C.Snuke wants to perform the following operatio ...

  6. k8s-prometheus 数据采集(node redis kubelet等)

    apiVersion: v1 kind: ConfigMap metadata: name: prometheus-config namespace: kube-ops data: prometheu ...

  7. VSFTP添加用户

    VSFTPD的安装网上有很多教程这里就不多说了,这里主要是针对做主机空间服务的朋友在安装好vsftpd后如何为用户增加ftp账号 先来看一看我们一般在*inux系统下面如何增加用户的 #adduser ...

  8. Java 私有构造函数的使用

    被private修饰的私有构造函数无法在其他类中调用,也就是该类无法在其他类中实例化. 这种情况常用的使用场景:1.单例模式: 2.防止实例化. 一.单例模式 单例模式是一种常用的设计模式,思想是单例 ...

  9. 怎样理解在函数中声明var x = y = 1后调用函数时, x是局部变量, y是全局变量

    下面这段代码在执行的时候, 打印的结果是1, Error: undefined; function fn() { var x = y = 1; } fn(); console.log(y); // 1 ...

  10. luogu2568GCD题解--欧拉函数

    题目链接 https://www.luogu.org/problemnew/show/P2568 分析 题目即求\(\sum_{i=1}^N \sum_{j=1}^N [gcd(i,j)\) \(is ...