几种单例模式的使用及比较

单例的使用一般分为三步:

(1)最简单的一种方式


<span style="white-space:pre">	</span>private static AudioManager mInstance; //第一步:一个私有静态的类成员变量

	private AudioManager() {} //第二步:一个私有的构造方法

	public static AudioManager getInstance() {//第三步:一个public的对外获取实例的方法
	<span style="white-space:pre">	</span>if (mInstance == null) {
			mInstance = new AudioManager();
		}
		return mInstance;
	}

这种方式只有在单线程的时候工作正常,设想在多线程的情况下,当两个线程同时运行到判断mInstance是否为null的if语句,并且mInstance没有创建时,这时两个线程都回去创建一个实例,此时就不符合单例的要求了。

(2)能在多线程下工作但线率不高的方式

由(1)可知,为了让其能在多线程下正常工作,需要加上一把同步锁,修改如下:

<span style="white-space:pre">	</span><span style="font-size:18px;">private static AudioManager mInstance; //第一步:一个私有静态的类成员变量

	private AudioManager() {} //第二步:一个私有的构造方法

	public static AudioManager getInstance() {//第三步:一个public的对外获取实例的方法
		synchronized (AudioManager.class) {
		<span style="white-space:pre">	</span>if (mInstance == null) {
			<span style="white-space:pre">	</span>mInstance = new AudioManager();
			}
		}
		return mInstance;
	}</span>

通过这种加同步锁的方式,我们可以保证在多线程的环境下只得到一个该类的实例,但我们每次通过getInstance()方法去取实例时,都会试图加上一个同步锁,而加锁是一个非常耗时的操作,在该实例存在时我们就应该尽量避免再去加锁。

(3)推荐使用的方式

<span style="font-size: 18px; "><span style="white-space:pre">	</span>/**
	 * 通过单例实现获取本类(AudioManager)对象
	 */
	private static AudioManager mInstance; //第一步:一个私有静态的类成员变量

	private AudioManager() {} //第二步:一个私有的构造方法

	public static AudioManager getInstance() {//第三步:一个public的对外获取实例的方法
		if (mInstance == null) {
			synchronized (AudioManager.class) {
				if (mInstance == null) {
					mInstance = new AudioManager();
				}
			}
		}
		return mInstance;
	}</span>

如果获取实例时需要给构造方法传入参数,直接在getInstance()里面加入参数即可,如:

<span style="font-size:18px;"><span style="white-space:pre">	</span>private String mDir;</span>
<span style="font-size:18px;"><span style="white-space:pre">	</span>private static AudioManager mInstance;//第一步:一个私有静态的类成员变量

	private AudioManager(String dir) {//第二步:一个私有的构造方法
		mDir = dir;
	}

	public static AudioManager getInstance(String dir) {//第三步:一个public的对外获取实例的方法
		if (mInstance == null) {
			synchronized (AudioManager.class) {
				if (mInstance == null) {
					mInstance = new AudioManager(dir);
				}
			}
		}
		return mInstance;
	}</span>

上面的getInstance方法里面通过两次 if 判断,控制只有当mInstance为null即没有创建时,才需要加锁操作。因为只在第一次的时候mInstance为null,因此只有在第一次试图创建实例的时候才需要加锁,相对于第二种方式效率会有很大的提高。

时间: 2024-10-19 21:09:45

几种单例模式的使用及比较的相关文章

五种单例模式

今天算是完完整整把老高的单例模式看了,差不多也懂了,个别不懂的再补吧,下面介绍一下5种单例模式: 饿汉式实现:线程安全,调用效率高.但是,不能延时加载. 懒汉式实现:线程安全,调用效率不高.但是,可以延时加载. 双重检测锁式:由于JVM底层内部模型原因,偶尔会出现问题,不建议使用. 静态内部类式:线程安全,调用效率高,可以延时加载. 枚举式:线程安全,调用效率高.但是,不能延时加载(避免反射和反序列化的漏洞). 以下先介绍一下5种单例模式: 饿汉式实现: /** *单例模式:饿汉模式 *线程安全

Java中的五种单例模式实现方法

[代码] Java中的五种单例模式实现方法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 package s

iOS开发笔记-两种单例模式的写法

iOS开发笔记-两种单例模式的写法 单例模式是开发中最常用的写法之一,iOS的单例模式有两种官方写法,如下: 不使用GCD #import "ServiceManager.h" static ServiceManager *defaultManager; @implementation ServiceManager +(ServiceManager *)defaultManager{ if(!defaultManager) defaultManager=[[self allocWith

7、java实现的两种单例模式

/* 两种单例模式的演示 */ //饿汉式 class Signal { private Signal(){} private Signal s = new Signal(); public static Signal getInstance() { return s; } } //懒汉式 class Signal { private Signal(){} private Signal s = null; public static Signal getInstance() { if(s ==

8种单例模式写法助你搞定面试

1. 单例模式常见问题 为什么要有单例模式 单例模式是一种设计模式,它限制了实例化一个对象的行为,始终至多只有一个实例.当只需要一个对象来协调整个系统的操作时,这种模式就非常有用.它描述了如何解决重复出现的设计问题, 比如我们项目中的配置工具类,日志工具类等等. 如何设计单例模式 ? 1.单例类如何控制其实例化 2.如何确保只有一个实例 通过一下措施解决这些问题: private构造函数,类的实例话不对外开放,由自己内部来完成这个操作,确保永远不会从类外部实例化类,避免外部随意new出来新的实例

五种单例模式实现

核心作用: 保证一个类只有一个实例,并向外提供一个访问该实例的访问点. 常见场景: 数据库连接池的设计一般也是单例模式 在Servlet编程中,每个Servlet也是单例模式 在Spring中,默认创建的bean也是单例模式 ...... 优点: 1.由于每个类只创建一个实例,大大减少了内存的开销. 2.单例模式提供全局访问点,可以实现共享资源访问. 常见的五种单例模式实现方法: 饿汉式(线程安全,效率高,不能延迟加载) 懒汉式(线程安全,效率不高,可以延迟加载) DCL懒汉式(线程安全,效率还

两种单例模式的写法

iOS的单例模式有两种官方写法,如下: (1)不使用GCD #import "ServiceManager.h" static ServiceManager *defaultManager; @implementation ServiceManager +(ServiceManager *)defaultManager{ if(!defaultManager) defaultManager=[[self allocWithZone:NULL] init]; return default

几种单例模式的写法

方法一: public class Singleton1 {     private Singleton1(){         System.out.print("Singleton1 created");     }     private static Singleton1 instance = new Singleton1();     public static Singleton1 getInstance(){         return instance;     }

java两种单例模式

第一种 1 package com.atguigu.javase; 2 import java.io.IOException; 3 4 /** 5 * @author _aL0n4k 6 * @version 1.0 7 * @time 2015年9月2日 下午6:12:52 8 */ 9 public class Singleton_HungerMode { //单例模式 - 饥饿式 10 private Singleton_HungerMode() {} //把构造器设置为private,这

五种单例模式----来自脚本之家

本文为大家分享了Python创建单例模式的5种常用方法,供大家参考,具体内容如下 所谓单例,是指一个类的实例从始至终只能被创建一次. 方法1: 如果想使得某个类从始至终最多只有一个实例,使用__new__方法会很简单.Python中类是通过__new__来创建实例的: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 class Singleton(object):   def __new__(cls,*args,**kwargs):     if not hasattr(cls,