前言

我们都知道生活中好多小软件,有的支持多IP在线,有的仅仅局限于单个IP在线。为什么这样设计,在软件开发阶段就是,有需求就是发展。这就是软件开发的一个设计模式——懒汉式单例类和饿汉式单例类。

内容

现在的互联网发展很迅速,人们对保护自己隐私的意识也日益提高。所以单例模式就上场了,且看:

单例模式

定义:

单例模式保证一个类仅有一个实例,并提供了一个访问它的全局点。

解释:

用大白话来说就是 一条路,一次只让一个过,相当于种萝卜,一个坑只能种一个萝卜。官方讲通常我们可以让一个全局变量使得一个对象被访问,但它不能防止你实例化多个对象。一个最好的方法就是,让类自身负责保存它的唯一实例。这个类可以保证没有其他实例可以被创建,并且可以他可以提供一个访问该实例的方法。

看图:

代码也灰常简单哦:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
//作者:周丽同
//文件:单例模式 namespace ConsoleApplication2
{
class Singleton
{
private static Singleton instance; private Singleton ()//构造方法让其为private,这就堵死了外界利用new创建此类实例的可能;
{ } public static Singleton GetInstance()//此方法时获得本类实例的唯一全局访问点;
{
if (instance ==null )//若实例不存在,则new一个新的实例,否则返回已有的实例;
{
instance = new Singleton();
} return instance;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
//作者:周丽同
//文件:单例模式 namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
Singleton s1 = Singleton.GetInstance();
Singleton s2 = Singleton.GetInstance(); if (s1==s2 )//比较两次实例化后对象的结果是实例相同;
{
Console.WriteLine("两个对象是相同的实例。");
} Console.Read();
}
}
}

好处:

单例模式因为Singleton类封装它的唯一实例,这样它可以严格地控制客户是怎样访问以及何时访问它。就是对唯一实例的受控访问。

完善单例——多线程

对于单例模式,我们只是注意到了在实例化的时候防止实例化泛滥,但是考虑细节问题,多线程的程序中,同时访问Singleton类,调用里面的GetInstance()方法,也会有可能造成创建多个实例的现象,给我防止这个,可以给进程加一把锁来处理,相当于一个屋子只能进去一个人去完成任务,第一个人进去后把门锁了,防止后面的人去屋子里面完成在该时段的同样的任务。

见代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
//作者:周丽同
//文件:多线程时的单例
namespace 单例模式之懒汉与饿汉
{
class Singleton
{
private static Singleton instance;
private static readonly object syncRoot = new object();
//程序运行时创建一个静态只读的进程辅助对象;
private Singleton ()
{ } public static Singleton GetInstance()
{
lock (syncRoot )//在同一个时刻加了锁的那部分程序只有一个线程可以进入;
{
if (instance ==null )
{
instance =new Singleton ();
}
} return instance;
}
}
}

这里解释一下,Lock是确保当一个线程位于代码的临界区时,另一个线程不进入临界区。如果其他线程试图进入锁定的代码,则它将一直等待(即被阻止),直到该对象被释放。由于有了 lock,就保证了多线程下同上访问也不会造成多实例的生成。

多线程虽然解决了保证实例化一个。但是对于加锁的方式上不管有没有实例化对象都是先加了锁,这样看起来未免有点不合理。双重锁定解决了这种情况。

完善单例——双重锁定

它先是判断实例是否存在,不存在再枷锁处理。这样我们不用让线程每次都加锁,而只是在实例未被创建的时候再加锁处理,同时这样也能保证多线程的安全。这就是我们所说的Double-Check Locking。至于为什么判断Instance是否为空两次,第一次是判断是否有加锁的毕业,第二次是针对第二次以后进来的执行者是否执行实例化的判断。

见代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
//作者:周丽同
//文件:双重锁定 namespace 双重锁定
{
class Singleton
{
private static Singleton instance;
private static readonly object syncRoot = new object();
private Singleton()
{ } public static Singleton GetInstance()
{
if (instance ==null )//先判断实例是否存在,不存在再加锁处理;
{
lock (syncRoot )
{
//当instance不存在的情况下,当instance为 null并且同时有两个线程调用GetInstance()方法时;
//都可以通过第一重instance==null的判断。然后由于lock机制,这两个线程则只有一个进入,另一
//个在外排队等候。等另一个出来以后,另一个才能进入,如果没有第二重的instance==null,还是
//可以重新创建实例的。没有达到单例的目的。
if (instance ==null )
{
instance = new Singleton();
}
}
} return instance;
}
}
}

静态初始化

C#与公共语言运行库也提供了一种“静态初始化”方法,这种方法不需要开发人员显式地编写线程安全代码,即可解决多线程环境下它是不安全的问题。

见代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
//作者:周丽同
//文件:静态初始化 namespace 静态初始化
{
public sealed class Singleton//防止发生派生,而派生可能会增加实例;
{
//在第一次引用类的任何成员时创建实例。公共语言运行库负责处理变量初始化;
private static readonly Singleton instance = new Singleton();
private Singleton ()
{ } public static Singleton GetInstance()
{
return instance;
}
}
}

这个也实现了全局访问和实例化控制,公共静态属性访问实例提供了一个全局访问点。不同之处在于它利用公共语言运行库来初始化变量。构造方法和前面一样都是私有的,不能再类本身以外实例化Singleton类;其中instance变量标记为readonly(只读),表示只能在静态初始化期间或在类构造函数中分配变量。

总结

静态初始化的方式是在自己加载的时候就将自己实例化,需要提前占用资源,所以被形象的称之为饿汉式单例类;原先的单例模式处理方式要在第一次被引用时,才会将自己实例化,面临着多线程访问的安全性问题,需要做双重锁定这样的处理才可以保证安全,所以为懒汉式单例类。本人菜鸟一枚,如果不合适的地方,望大神斧正。

1、对比着学习更加容易理解知识。

2、永远不要相信一件东西可以近乎完美,只要发现总有更好的。

3、多做总结,多多回顾。

最后的最后,感谢您的宝贵时间~~~

设计模式——懒汉式单例类PK饿汉式单例类的更多相关文章

  1. 牛客网Java刷题知识点之什么是单例模式?解决了什么问题?饿汉式单例(开发时常用)、懒汉式单例(面试时常用)、单例设计模式的内存图解

    不多说,直接上干货! 什么是单例设计模式? 解决的问题:可以保证一个类在内存中的对象唯一性,必须对于多个程序使用同一个配置信息对象时,就需要保证该对象的唯一性. 如何保证? 1.不允许其他程序用new ...

  2. Java中的懒汉式单例与饿汉式单例实例详解

    懒汉式单例:线程非安全,当被调用的时候才创建实例,效率较高 public class LazySingleton { private static LazySingleton lazySingleto ...

  3. java 单利模式设计原理,饿汉式懒汉式,开发中推荐饿汉式

    单例模式的设计:  1 //Single类进内存,对象还没有存在,只有调用了getInstance方法时,才建立对象. //对象是方法被调用时,才初始化,也叫做对象的延时加载.成为:懒汉式. //Si ...

  4. JAVA单例模式:懒汉式,饿汉式

    今天复习了一下java的单例模式,写了懒汉式和饿汉式的实现例子.代码如下: 1.懒汉式单例 package com.lf.shejimoshi; /** * @classDesc: 类描述:(懒汉式单 ...

  5. Java面试 - 什么是单例设计模式,为什么要使用单例设计模式,如何实现单例设计模式(饿汉式和懒汉式)?

    什么是单例设计模式? 单例设计模式就是一种控制实例化对象个数的设计模式. 为什么要使用单例设计模式? 使用单例设计模式可以节省内存空间,提高性能.因为很多情况下,有些类是不需要重复产生对象的. 如果重 ...

  6. Java中单例设计模式,饿汉式和懒汉式

    Java中单例模式是一种常见的设计模式,单例模式的写法有好几种,这里主要介绍三种:懒汉式单例.饿汉式单例.登记式单例. 单例模式有以下特点: 1.单例类只能有一个实例. 2.单例类必须自己创建自己的唯 ...

  7. java基础10 单例模式之饿汉式和懒汉式单例

    前言: 软件行业中有23中设计模式 单例模式    模版模式    装饰者模式    观察者模式    工厂模式    ........... 单例模式 1. 单例模式包括 1.1 饿汉式单例 1.2 ...

  8. Singleton模式(单例模式) 饿汉式和懒汉式

    目的:整个应用中有且只有一个实例,所有指向该类型实例的引用都指向这个实例. 好比一个国家就只有一个皇帝(XXX),此时每个人叫的“皇帝”都是指叫的XXX本人; 常见单例模式类型: 饿汉式单例:直接将对 ...

  9. Java中常用来处理时间的三个类:Date、Calendar、SimpleDateFormate,以及Java中的单例设计模式:懒汉式、饿汉式以及静态内部类式

    (一)java.util.Date类 1.该类有一个long类型的属性:用来存放时间,是用毫秒数的形式表示,开始的日期是从1970年1月1号 00:00:00.    2.该类的很多方法都已经过时,不 ...

随机推荐

  1. php导出内容到txt并自动弹出下载文件

    php将内容保存到txt文件中,并自动弹出下载文件窗口的方法: $id=array('我爱学习网http://www.5ixuexiwang.com','汇享在线工具箱http://tool.huix ...

  2. PHP获取当前日期及本周一是几月几号的方法

    这篇文章主要介绍了PHP获取当前日期及本周一是几月几号的方法,涉及php时间戳.日期转换与运算相关操作技巧,需要的朋友可以参考下 本文实例讲述了PHP获取当前日期及本周一是几月几号的方法.分享给大家供 ...

  3. 《java编程思想》:散列的原理

    以实现一个简单的HashMap为例,详细讲解在code之中. 简单解释散列原理: 1.map中内建固定大小数组,但是数组并不保存key值本身,而是保存标识key的信息 2.通过key生成数组角标,对应 ...

  4. Ubuntu 下安装mysql

    本文引用自 https://www.cnblogs.com/jpfss/p/7944622.html 此篇为http://www.cnblogs.com/EasonJim/p/7139275.html ...

  5. 8th

    2017-2018-2 20179212<网络攻防实践>第8周作业 视频学习 Kali权限维持之后门 权限维持包含Tunnel工具集.Web后门.系统后门三个子类.其中系统后门与web后门 ...

  6. LOJ2722 「NOI2018」情报中心

    「NOI2018」情报中心 题目描述 C 国和D 国近年来战火纷飞. 最近,C 国成功地渗透进入了D 国的一个城市.这个城市可以抽象成一张有$n$ 个节点,节点之间由$n - 1$ 条双向的边连接的无 ...

  7. bzoj 4504: K个串 可持久化线段树+堆

    题目: Description 兔子们在玩k个串的游戏.首先,它们拿出了一个长度为n的数字序列,选出其中的一 个连续子串,然后统计其子串中所有数字之和(注意这里重复出现的数字只被统计一次). 兔子们想 ...

  8. java判断一个类是否公共类

    Modifier.isPublic([类].getModifiers()) Modifier.isAbstract([类].getModifiers())

  9. http之pragma

    关于Pragma:no-cache,跟Cache-Control: no-cache相同.Pragma: no-cache兼容http 1.0 ,Cache-Control: no-cache是htt ...

  10. centos 6 rsync+inotify 实时同步

    主机名.ip: server 172.31.82.184 client  172.31.82.185 需求: 1.server端 ”/data/server“ 做为client端 “/data/cli ...