JAVA设计模式—单例模式
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JAVA设计模式—单例模式相关的知识,希望对你有一定的参考价值。
一、设计简介
1、什么是设计模式 ?
设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。
1994年,有四位作者:Erich Gamma,Richard Helm,Ralph Johnson和John Vlissides发表了一本题为《设计模式 - 可重用的面向对象软件元素》的图书,该书在软件开发中开创了设计模式的概念。
2、设计模式的分类?
创建型模式:对象实例化的模式,创建型模式用于解耦对象的实例化过程。
结构型模式:把类或对象结合在一起形成一个更大的结构。
行为型模式:类和对象如何交互,及划分责任和算法。
二、设计模式详解
1.单例模式
单例模式,它的定义就是确保某一个类只有一个实例,并且提供一个全局访问点。
单例模式具备典型的3个特点:1、只有一个实例。 2、自我实例化。 3、提供全局访问点。
单例模式的应用场景:servlet、springMVC、连接池、线程池、枚举。
单例好处:节约内存,重复利用,方便管理。
缺点:线程安全问题
单例的创建方式:
1.饿汉式:类初始化时,会立即加载对象,线程天生安全,调用效率高。相对来说占内存
/* 饿汉式 */ public class Demo1 { //初始化创建对象,调用效率高,但是如果该对象不使用,会占用内存 private static final Demo1 d1 = new Demo1(); //初始化构造方法 private Demo1(){} //对外提供同意的获取对象的方法 public static Demo1 getInstands(){ return d1; } }
2.懒汉式:类初始化时,不会初始化对象,真正需要使用时才会创建对象。线程不安全。
/* 懒汉式 */ public class Demo2 { private static Demo2 d2; //私有化构造 private Demo2(){} //效率低,线程不安全,需要加锁 public static synchronized Demo2 getInstance(){ if(d2 == null){ d2 = new Demo2(); } return d2; } }
3.静态内部类:结合了懒汉式和饿汉式的优点,真正需要时才会加载,加载类是线程安全的
4.枚举单例:使用枚举实现单例,实现简单,效率高,枚举本身就是单例。
public class Demo3 { private Demo3(){} public static Demo3 getInstance(){ return SingletonEnum.INSTANCE.getInstance(); } static enum SingletonEnum{ INSTANCE; private Demo3 d3; private SingletonEnum(){ d3 = new Demo3(); } public Demo3 getInstance(){ return this.d3; } } public static void main(String[] args) { Demo3 demo1 = Demo3.getInstance(); Demo3 demo2 = Demo3.getInstance(); System.out.println(demo1 == demo2); } }
5.双重检测锁(不推荐使用)
public class Demo4 { private Demo4(){} private static Demo4 volatile d4; public Demo4 getInstance(){ if(d4 == null){ synchronized (Demo4.class){ if(d4 == null){ d4 = new Demo4(); } } } return d4; } }
注意:双重检测可能会出现重排序的问题,在JDK中,JAVA语言为了维持顺序内部的顺序化语义,也就是为了保证程序的最终运行结果需要和在单线程严格意义的顺序化环境下执行的结果一致,程序指令的执行顺序有可能和代码的顺序不一致,这个过程就称之为指令的重排序。指令重排序的意义在于:JVM能根据处理器的特性,充分利用多级缓存,多核等进行适当的指令重排序,使程序在保证业务运行的同时,充分利用CPU的执行特点,最大的发挥机器的性能!
Volatile类型的变量不会被缓存在寄存器中(寄存器中的数据只有当前线程可以访问),或者其他对CPU不可见的地方,每次都需要充主存中读取对应的数据,这保证每次对变量的修改,其他线程也是可见的,而不是仅仅修改自己线程的局部变量,在happens-before发则中,对一个volatile变量进行写操作后了,此后的任何读操作都可见该次写操作的结果。
java并发重排序推荐博客:https://www.cnblogs.com/longshiyVip/p/5211476.html
以上是关于JAVA设计模式—单例模式的主要内容,如果未能解决你的问题,请参考以下文章