java基础之设计模式之单例模式
关于单例模式:
单例,即单一实例。因为在一些情况下,某些类的对象,我们只需要一个就可以了,所以我们要用到单例模式。
单例模式的目的是使得一个类中的一个静态对象成为系统中的唯一实例,提供一个访问该实例的方法。并阻止其他对象实例化其自己的单例对象的副本,从而确保所有对象都访问唯一实例。
单例模式特点:其在整个应用程序的生命周期中只存在一个实例。
单例模式分为懒汉式和饿汉式两种
这里先贴出代码,然后再做解释,便于理解。
懒汉式单例模式核心代码:
1 package com.wxb.singleton;
2
3 public class Singleton_Lazy {
4 /* --创建私有静态的自身实例对象-- */
5 private static Singleton_Lazy uniqueInstance = null;
6
7 /* --私有的构造方法,避免外界利用构造方法创建多个实例-- */
8 private Singleton_Lazy() {
9
10 }
11
12 /* --获取静态实例的方法--
13 * --该方法是静态的,可以通过类名直接调用--
14 */
15 public static Singleton_Lazy getUniqueInstance() {
16 if (null == uniqueInstance) {
17 uniqueInstance = new Singleton_Lazy();
18 }
19 return uniqueInstance;
20 }
21 }
懒汉式单例模式特点:懒汉模式的单例类的唯一实例对象是在第一次使用 getUniqueInstance()时实例化的。如果我们不调用 getUniqueInstance()的话,这个实例是不会存在的,即为 初始值null。可以看出如果不去动它的话,它自己是不会实例化的,所以形象的称之为懒汉模式。
饿汉式单例模式核心代码:
1 package com.wxb.singleton;
2
3 public class Singleton_Hungry {
4 /*
5 * --在初始化时,就实例化了静态的自身实例对象-- --饿汉式的缺点也在于此:浪费内存--
6 */
7 private static Singleton_Hungry uniqueInstance = new Singleton_Hungry();
8
9 /* --私有的构造方法,避免外界利用构造方法创建多个实例-- */
10 private Singleton_Hungry() {
11
12 }
13
14 /* --获取静态实例的方法--
15 * --该方法是静态的,可以通过类名直接调用--
16 */
17 public static Singleton_Hungry getUniqueInstance() {
18 return uniqueInstance;
19 }
20 }
饿汉单例模式特点:之所以称之为饿汉,是因为肚子饿了,人也会变得主动了,所以饿汉模式下的单例类其自己就会主动实例化该单例类的唯一实例对象。
一般懒汉式单例模式较为常用。
对于唯一实例的验证:
1 package com.wxb.singleton;
2
3 public class SingletonTest {
4 /* --单例模式唯一实例的测试|调用懒汉式单例验证-- */
5 public static void main(String[] args) {
6 Singleton_Lazy singleton_Lazy1 = Singleton_Lazy.getUniqueInstance();
7 Singleton_Lazy singleton_Lazy2 = Singleton_Lazy.getUniqueInstance();
8 if (singleton_Lazy1.equals(singleton_Lazy2)) {
9 System.out.println("Singleton_Lazy1 and singleton_Lazy2 are the same instance");
10 }
11 else {
12 System.out.println("Singleton_Lazy1 and singleton_Lazy2 are different instance");
13 }
14 }
15 }
输出结果:

可以看出虽然两次调用getUniqueInstance(),但是访问的是同一个实例。
对于懒汉式单例模式,还存在着多线程安全问题
在多线程中,如果在一开始调用 GetUniqueInstance()时,是由两个线程同时调用的,这样的话,两个线程均会进入GetUniqueInstance(),而后由于是第一次调用 GetUniqueInstance(),所以静态变量 uniqueInstance为 null ,这样的话,就会让两个线程均通过 if 语句的条件判断,然后调用 new GetUniqueInstance()了。
所以问题就出来了,因为有两个线程,所以会创建两个实例,这便违反了单例模式的初衷,使得单例模式在多线程中出现不安全的问题。
这个问题我们可以通过线程锁机制对单例模式做相应的优化,即先将一个线程锁定,然后等这个线程完成以后,再让其他的线程访问GetUniqueInstance()中的 if 段语句。
双重校验锁形式单例模式核心代码:
1 package com.wxb.singleton;
2
3 public class Singleton_Lazy_Safe {
4 /* --创建私有静态的自身实例对象-- */
5 private static Singleton_Lazy_Safe uniqueInstance = null;
6
7 /* --私有的构造方法,避免外界利用构造方法创建多个实例-- */
8 private Singleton_Lazy_Safe() {
9
10 }
11
12 /* --获取静态实例的方法--
13 * --该方法是静态的,可以通过类名直接调用--
14 */
15 public static Singleton_Lazy_Safe getUniqueInstance() {
16 /* --双重校验锁-- */
17 if (null == uniqueInstance) {
18 synchronized (Singleton_Lazy_Safe.class) {
19 if (null == uniqueInstance) {
20 uniqueInstance = new Singleton_Lazy_Safe();
21 }
22 }
23 }
24 return uniqueInstance;
25 }
26 }
关于使用双重校验的原因:
如果有两个线程同时到达,即同时调用了GetUniqueInstance(),此时由于 uniqueInstance == null ,所以两个线程都可以通过第一重的 singleton == null 校验,
进入第一重 if 语句后,由于存在锁机制,所以会有一个线程进入 lock 语句并进入第二重 uniqueInstance == null ,而另外的一个线程则会在 synchronized 语句的外面等待。
当第一个线程执行完 new Singleton_Lazy_Safe()语句后,便会退出锁定区域,此时,第二个线程便可以进入synchronized语句块,此时,如果没有第二重 uniqueInstance == null 的话,那么第二个线程还会继续调用 new Singleton_Lazy_Safe()语句,这样第二个线程又会创建一个 Singleton 实例,违反了“唯一实例”。
由于饿汉式单例类类被加载的时候,就会自行初始化uniqueInstance这个静态的自身实例对象。而不是在第一次调用GetUniqueInstance()时再来实例化单例类的唯一实例,所以饿汉式单例不需要编写多线程安全代码。
java基础之设计模式之单例模式的更多相关文章
- 第二十七节:Java基础面向对象-静态,单例模式,继承详情知识点
前言 Java基础面向对象-静态,单例模式,继承详情知识点.静态-static关键字,static变量,静态代码块,代码块(不加静态),对象创建过程,单例模式,继承. 静态-static关键字 // ...
- java 23 - 2 设计模式之单例模式
单例模式:保证类在内存中只有一个对象. 如何保证类在内存中只有一个对象呢? A:把构造方法私有 B:在成员位置自己创建一个对象 C:通过一个公共的方法提供访问 单例模式之饿汉式: (一进来就造对 ...
- Java基础-单列设计模式
概念: Java中单例模式是一种常见的设计模式,单例模式的写法有好几种,这里主要介绍三种:懒汉式单例.饿汉式单例.登记式单例. 单例模式有以下特点: 1.单例类只能有一个实例. 2.单例类必须自己创建 ...
- Java进阶篇设计模式之一 ----- 单例模式
前言 在刚学编程没多久就听说过设计模式的大名,不过由于当时还是个彻彻底底的菜鸟,并没有去触碰.直到在开始工作中对简单的业务代码较为熟悉之后,才正式的接触设计模式.当时最早接触的设计模式是工厂模式,不过 ...
- Java中的设计模式之单例模式
Java中的单例模式 设计模式是软件开发过程中经验的积累 一.单例模式 1.单例模式是一种常用的软件设计模式,通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控 ...
- Java基础-工厂设计模式(三锅的肥鸡)
---恢复内容开始--- 1)还没有工厂时代:假如还没有工业革命,如果一个你要一架飞机,一般的做法是自己去建造一架飞机,然后拿来开 通常的结果就是 有些时候 要么专科螺钉 没打好 要么就是 那个 ...
- JAVA基础—适配器设计模式
适配器概念 在计算机编程中,适配器模式将一个类的接口适配成用户所期待的.使用适配器,可以使接口不兼容而无法在一起工作的类协调工作,做法是将类自己包裹在一个已经存在的类中. JDK对适配器设计模式的应用 ...
- [Java面经]干货整理, Java面试题(覆盖Java基础,Java高级,JavaEE,数据库,设计模式等)
如若转载请注明出处: http://www.cnblogs.com/wang-meng/p/5898837.html 谢谢.上一篇发了一个找工作的面经, 找工作不宜, 希望这一篇的内容能够帮助到大 ...
- 【Java基础】Java设计模式简介
什么是设计模式 设计模式(Design pattern)是一套被反复使用.被多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了可重用代码.让代码更容易被他人理解.保证代码可靠性.设计 ...
随机推荐
- vue源码中computed和watch的解读
computed 会基于其内部的 响应式依赖 进行缓存. 只在相关 响应式依赖发生改变 时 它们才会重新求值. 可以在将模板中使用的常量放在计算属性中. watch 监听数据变化,并在监听回调函数中返 ...
- css 快速入门 系列 —— 浮动
浮动 以 mdn float 文档 为基础,逐一介绍浮动的本质.浮动的诸多特性.清除浮动以及块格式化上下文(bfc). 概念 当一个元素浮动之后,它会被移出正常的文档流,然后向左或者向右平移,一直平移 ...
- 初识MASA Blazor
MASA Blazor是一个Blazor的UI组件库.就像大家写前端熟知的Bootstrap, Ant Design一样. MASA Blazor官网地址:https://blazor.masasta ...
- python 面向对象:类方法&静态方法
一.类方法 1.1 概念和语法说明 类方法就是针对类对象定义的方法.在类方法内部可以直接访问类属性或者调用其他的类方法 语法如下: @classmethod def 类方法名(cls): pass 说 ...
- linux安全篇:禁止频繁访问的ip访问nginx
实验环境 版本:redhat6.5ip:172.16.1.100,172.16.10软件:nginx 172.16.1.10部署nginx [root@localhost tools]# lsngin ...
- Ribbon原理与应用
一.定义 Ribbon是请求的负载均衡器,它为我们提供了几种负载均衡算法:轮询.随机等. 二.配置 spring: cloud: loadbalancer: retry: enabled: true ...
- test_3 简单密码破解
题目描述:密码是我们生活中非常重要的东东,我们的那么一点不能说的秘密就全靠它了.哇哈哈. 接下来渊子要在密码之上再加一套密码,虽然简单但也安全. 假设渊子原来一个BBS上的密码为zvbo9441987 ...
- vulhub安装教程
0x00 vulhub介绍 Vulhub是一个基于docker和docker-compose的漏洞环境集合,进入对应目录并执行一条语句即可启动一个全新的漏洞环境,让漏洞复现变得更加简单,让安全研究者更 ...
- session反序列化
先来了解一下关于session的一些基础知识 什么是session?在计算机中,尤其是在网络应用中,称为"会话控制".Session 对象存储特定用户会话所需的属性及配置信息.这样 ...
- Manacher算法求解回文字符串
Manacher算法可以在\(O(N)\)时间内求解出一个字符串的所有回文子串(正反遍历相同的字串). 注:回文串显然有两种,一种是奇数长度,如abczcba,有一个中心字符z:另外一种是偶数个长度, ...