单例模式是一个老生常谈的问题,这里对单例模式的实现做一下总结。

 

分类

* 懒汉模式
* 饿汉模式
* IoDH技术-懒汉模式与饿汉模式的结合
优势与劣势

* 懒汉模式
* 饿汉模式
* IoDH技术-懒汉模式与饿汉模式的结合
 

 

分类

懒汉模式

 
 懒汉模式是一种直到单例模式需要使用的时候才进行加载的技术。单例模式重要的一个点,是要保证多线程操作的正确性。为此,不同的懒汉模式实现上有了多种确保线程安全的方式。

   synchronized 可以确保方法的线程安全性,具体的做法用使用 sychronized 修饰的方法和 sychronized
修饰的代码块两种方式。

 

synchronized 方法修饰的单例模式
package mode; /** * Created by szh on 2020/6/28. * * @author szh */ public
class SingletonOne { private static SingletonOne singletonOne = null; private
SingletonOne() { } public synchronized static SingletonOne getInstance(){
if(singletonOne == null){ singletonOne = new SingletonOne(); } return
singletonOne; } public static void main(String[] args) {
SingletonOne.getInstance(); System.out.println("------------------------"); } }
   上述代码存在一定的问题,每次调用 getInstance() 时都需要进行线程锁定判断,在多线程高并发访问环境中,将会导致系统性能大大降低。

 

synchronized 代码块修饰的单例模式

 针对 synchronized 修饰的方法,可以减低锁的粒度,降低为代码块级别,下面是具体的代码:
package mode; /** * Created by szh on 2020/6/28. * * @author szh */ public
class SingletonTwo { private static volatile SingletonTwo singletonTwo = null;
private SingletonTwo() { System.out.println("init"); } public static
SingletonTwo getInstance() { if (singletonTwo == null) { synchronized
(SingletonTwo.class) { if (singletonTwo == null) { singletonTwo = new
SingletonTwo(); } } } return singletonTwo; } public static void main(String[]
args) { SingletonTwo.getInstance();
System.out.println("======================="); } }
* volatile 修饰静态成员变量
      需要注意一点,需要用 volatile 修饰 静态成员变量,保证不被代码优化导致的双重检查失效。但是也需要注意,volatile 关键字会屏蔽
Java虚拟机锁做的一些代码优化,可能会导致系统运行效率较低。因此,使用双重检查锁来实现单例模式也不是一种完美的实现方式。

 

 

饿汉模式

饿汉模式,可以确保类在被加载时就将自己实例化,可以不需要考虑多线程访问的问题。

下面是具体的代码
package mode; /** * Created by szh on 2020/6/29. */ public class
SingletonThree { private static SingletonThree singletonThree = new
SingletonThree(); private SingletonThree(){ System.out.println("init"); }
public static SingletonThree getInstance(){ return singletonThree; } public
static void main(String[] args){ SingletonThree.getInstance();
System.out.println("-----------------------------"); } }
   饿汉模式也存在了一定问题,上面的代码虽然解决了线程安全的问题,但是每次调用 getInstance()
时候都需要进行线程锁定判断,在多线程高并发访问环境中,将会导致系统性能大大降低。

 

 

IoDH技术-懒汉模式与饿汉模式的结合
package mode; /** * Created by szh on 2020/6/29. */ public class SingletonFour
{ private SingletonFour(){ System.out.println("init"); } private static class
SingletonFourInner{ private final static SingletonFour instance = new
SingletonFour(); } private static SingletonFour getInstance(){ return
SingletonFourInner.instance; } public static void main(String[] args){
SingletonFour.getInstance();
System.out.println("----------------------------"); } }
解析 :

  静态单例对象并没有作为Singleton的成员变量直接实例化,因此类加载时候并不会实例化Sinleton。

  只有第一次调用 getInstance() 时将加载内部类,由Java虚拟机确保线程安全性,确保该成员变量只能初始化一次。

 

 

 

 

优势与劣势

*
懒汉模式

优势:类只要使用的时候才进行加载

劣势:1)需要复杂的代码确保线程安全性

           2)即使确保线程安全性,效率并非最高

 

*
饿汉模式

优势:代码简单,不需要考虑多线程安全问题

劣势:在类未被使用的时候就生成实例,性能最差

 

*
IoDH技术-懒汉模式与饿汉模式的结合

优势:性能最高

劣势:具有语言特性,Java外其他语言并不支持

技术
©2019-2020 Toolsou All rights reserved,
Redis 计数器 高并发的应用pytorch之ResNet18(对cifar10数据进行分类准确度达到94%)在Vue中使用Web Worker函数基本定义和使用‘未完待续 如何建设数据安全体系?最优化方法总结:公式解、数值优化、求解思想c++内存 指针越界检测机制_CrtMemBlockHeadePython垃圾回收与内存泄露蚂蚁集团香港IPO获得中国证监会批准Keras保存与加载模型(JSON+HDF5)