`

单例模式--只有一个实例

阅读更多

什么是单例模式:

 

 

确保一个类只有一个实例,并提供一个全局访问点。

注意:使用起来类似静态方法,但是它不是静态方法,而是类。需要new关键字来实例化。

 

 

单例模式的基本使用方式可以概括为3个步骤:

1.创建一个private静态变量;

2.创建一个private空构造器;

3.创建一个public静态访问点,用来将唯一实例返回给外部调用者。

 

基本使用方式:

 

方法1:

 

public class SingletonCommon {

	private static SingletonCommon uniqueInstance;//步骤一
	
	private SingletonCommon(){}//步骤二
	
	public static SingletonCommon getInstance()//步骤三
	{
		if(uniqueInstance == null)
		{
			uniqueInstance = new SingletonCommon();
		}
		return uniqueInstance;
	}
}

 

虽然看上去简单。但是这个类还存在问题。

我们的程序基本都是多线程的。就存在这样的可能:多个线程同时去调用这个实例,假设这个时候uniqueInstance == null,而线程A执行到if(uniqueInstance == null)这句语句,这时候系统线程调度,线程A交出cpu。转而执行B线程中的代码,而在B线程中也有可能访问这个类,那么它访问的时候,发现uniqueInstance == null,自然就创建一个实例。等到cpu的使用权回到A的时候,A从刚才停住的地方开始执行,也创建了一个实例!所以这个时候问题就出现了。

 

那么怎么解决这个问题呢?

 

方法:2:

 

使用synchronized关键字

通过这个关键字可以迫使线程在进入这个方法前,要等别的线程离开这个方法,这样就可以不会有两个线程同时访问这个类了,我们的问题就解决了。而且使用起来很简单,仅仅多了一个synchronized关键字而已。

 

 

public class SingletonSynchronized {

	private static SingletonSynchronized uniqueInstance;
	
	private SingletonSynchronized(){}
	
	public static synchronized SingletonSynchronized getInstance()
	{
		if(uniqueInstance == null)
		{
			uniqueInstance = new SingletonSynchronized();
		}
		return uniqueInstance;
	}
}

 

但是这样也存在一个问题:效率。

每次调用getInstance()的时候都要进行同步,会造成负担。

那么怎么办才能提高效率呢?

 

方法3:

使用 双重检查加锁

 

 

利用双重检查加锁,首先检查是否已经创建了实例,如果还没有创建,才进行同步

这样一来就只有第一次会同步。这样就可以提高效率。

 

 

这里需要引入volatile关键字,这个关键字确保当uniqueInstance变量被初始化成SingletonDoubleLocking实例时,

多个线程正确地处理uniqueInstance变量。

 

 

public class SingletonDoubleLocking {

	private volatile static SingletonDoubleLocking uniqueInstance;
	
	private SingletonDoubleLocking(){}
	
	public static SingletonDoubleLocking getInstance()
	{
		synchronized (SingletonDoubleLocking.class) 
		{
			if(uniqueInstance == null)
			{
				uniqueInstance = new SingletonDoubleLocking();
			}
		}
	        return uniqueInstance;
	}
}

 

这样做似乎已经无懈可击了。但是还有问题存在!

问题是:双重检查加锁不适用于1.4及更早版本的Java

 

那还有别的方法吗?

我们知道前面的做法主要都是为了围绕着如何避免产生多个单例。

那能不能在调用getInstance()之前就生成实例呢?这样不就避免了所有的问题了吗?

 

方法4:

急切创建实例

 

在虚拟机加载这个类的时候就马上创建单例,这样就确保了在任何线程访问这个变量的时候,该实例都已经存在了。

 

 

public class SingletonEagerly {

	private static SingletonEagerly uniqueInstance = new SingletonEagerly();//虚拟机加载这个类的时候,这个类就已经被创建
	
	private SingletonEagerly(){}
	
	public static SingletonEagerly getInstance()
	{
		return uniqueInstance;//不需要判断是否为null,直接返回就可以了
	}
}

 

 

 

 

总结:

 

方法1:最普通的单例,建议不要这样使用,以免出问题。

 

方法2:使用synchronized关键字,使得每个线程进入这个方法之前,要等候别的线程离开这个方法才进入。对程序性能要求不高的的情况下可以使用,仅仅比普通的单例模式多了一个关键字而已。

 

方法3:双重检查加锁法,使用volatile关键字,它确保了变量被初始化为实例时,多个线程能够正确地处理变量。这是个不错的选择,但是要注意不能用于java1.4及之前的java版本。在Android中是可以选择这样做的,因为一般我们选择的jdk都是1.5及以上的。

 

方法4:急切创建实例法,如果这个类的不大,负担不重,那么可以考虑直接在JVM加载的这个类的时候,直接就生成实例。

 

 

 

我将上面4种方法,写成一个Android上可以运行的demo,demo中有两个Activity,在这两个Activity中通过单例的调用方式都将单例的的地址打印出来。我们可以看见,它们在内存中的物理地址一样,则表明它们是同一个对象。

如图所示:

 

 

 

 

 

 

 

有兴趣的同学可以下载来看看:

 

https://github.com/michaelye/SingletonPattern

 

 

 

 

 

 

 

 

  • 大小: 68.2 KB
  • 大小: 64.7 KB
1
1
分享到:
评论

相关推荐

    单例模式,single

    单例模式适合于一个类只有一个实例的情况,比如窗口管理器,打印缓冲池和文件系统,它们都是原型的例子。典型的情况是,那些对象的类型被遍及一个软件系统的不同对象访问,因此需要一个全局的访问指针,这便是...

    Java设计模式之单例模式

    目录 单例模式的概念 单例模式的要点 单例模式类图 单例模式归类 单例模式的应用场景 单例模式解决的问题 单例模式的实现方式 单例模式实现方式对比 单例模式的概念 单例模式,顾名思义就是只有一个实例,并且由它...

    单例模式的要点及模式

    单例模式(singleton)顾名思义,就是只有一个实例。作为对象的创建模[GOF95], 单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。这个类称为单例类。

    java模式之单例模式

    单例模式确保一个类只有一个实例,自行提供这个实例并向整个系统提供这个实例。 特点: 1,一个类只能有一个实例 2,自己创建这个实例 3,整个系统都要使用这个实例 例: 在下面的对象图中,有一个"单例对象",...

    Java 单例模式.pptx

    作为对象的创建模式, 单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。 PPT详细了单例模式的实现和使用场景

    设计模式学习之单例模式

    单例模式,顾名思义,只有一个实例,因此这种模式只有在真正的需求“单一实例”的时候使用。它提供一种方法来确保某一特定类型有且只有一个实例。而且自行实例化,并向外部提供这个单一实例。 在它核心结构中,只...

    java:单例模式 作为对象的创建模式

    作为对象的创建模式, 单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。这个类称为单例类譬如每台计算机可以有若干个打印机,但只能有一个Printer,以避免两个打印作业同时输出到打印机...

    单例模式Java实现

    单例模式是最简单的一种设计模式,确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例, 本资源提供了用java语言实现简单的单例模式,供初学者参考

    设计模式之单例模式源码demo

    单例模式,是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中,应用该模式的类一个类只有一个实例。即一个类只有一个对象实例。

    单例模式,属于创建类型的一种常用的软件设计模式 通过单例模式的方法创建的类在当前进程中只有一个实例(根据需要,也有可能一个线程中

    在懒汉式基础上利用synchronize关键字和volatile关键字确保第一次创建时没有线程间竞争而产生多个实例,仅第一次创建时同步,性能相对较高 登记式。作为创建类的全局属性存在,创建类被装载时创建 枚举。java中枚举...

    软件体系结构程序.zip

    外教安排战术:单例模式---一个球队只有一个外教,创建唯一实例,并调用他的方法。 翻译:适配器模式----实现目标接口外教没有的“说中文”的方法。 更换战术:策略模式---通过实现不同的具体策略实现抽象的策略,...

    单例模式案例和笔记,通过案例来了解单例模式

    Java一共有23种设计模式,单例模式就是指一个类只有一个实例,且该类能自行创建这个实例的一种模式。可以避免因打开多个任务管理器窗口而造成内存资源的浪费,或出现各个窗口显示内容的不一致等错误。比如咱们电脑...

    单例模式代码.rar

    Java中单例(Singleton)模式是一种广泛使用的设计模式。单例模式的主要作用是保证在Java程序中,某个类只有一个实例存在...

    使用Java单例模式实现一个简单的登录验证系统.txt

    这个代码实现了一个简单的登录验证系统。首先定义了一个LoginSystem类,用来表示登录验证系统,包括用户名和密码两...由于单例模式保证了只有一个LoginSystem对象存在,因此可以避免多个线程同时访问同一个实例的问题。

    Python单例模式实例详解

    单例模式:保证一个类仅有一个实例,并提供一个访问他的全局访问点。 实现某个类只有一个实例的途径: 1,让一个全局变量使得一个对象被访问,但是他不能防止外部实例化多个对象。 2,让类自身保存他的唯一实例,这...

    第9章_单例模式.ppt

    如何保证一个类只有一个实例并且这个实例易于被访问呢?定义一个全局变量可以确保对象随时都可以被访问,但不能防止我们实例化多个对象。 一个更好的解决办法是让类自身负责保存它的唯一实例。这个类可以保证没有...

    单例模式Singleton(java源码)

    单例模式的特点有三: 单例类只能有一个实例。 单例类必须自己创建自己的唯一实例。 单例类必须给所有其他对象提供这一...Instance()方法负责检验并实例化自己,然后存储在静态成员变量中,以确保只有一个实例被创建。

    Singleton(单例模式)

    在Java应用中,单例对象能保证在一个JVM中,该对象只有一个实例存在。这样有几个好处: 1、某些类创建比较频繁,对于一些大型的对象,这可以节省一笔很大的系统开销。 2、省去了new操作符,降低了系统内存的使用频率...

    C++ 单例模式的详解及实例

    C++ 单例模式的详解及...(1)确保一个类只有一个实例被建立 (2)提供了一个对对象的全局访问指针 (3)在不影响单例类的客户端的情况下允许将来有多个实例 2.怎样实现单例模式 一个简单的单例模式该怎样去实现

    单例模式 Singleton Pattern

    单例模式(Singleton Pattern)是 Java 中最...这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

Global site tag (gtag.js) - Google Analytics