有人说单件模式是最简单的模式,因为它只有一个类,但其实它还有一些值得注意的地方,就如:出现并发性时,单件可能已经不是单件了。
先说一下,我们为什么要用到单件模式,当我们用到这些对象如:线程池,缓存,注册表和日志对象等,事实上,这些对象我们只能有一个实例,不然会导致很多问题出现,所以我们要将它弄成单件的。
可能你会说利用程序员之间的约定或是利用全局变量就可以做到啊,如:java的静态变量。是的,但全局变量有一个缺点,就是它必须在程序一开始就要创建好,万一这个对象非常耗费资源,而程序又一直没用到它,那不是很浪费吗?而单件模式就克服了这个缺点。
到底如何实现这个单件模式呢?首先这个类只能实例化一次,那就说明它的构造方法不能公开;那不公开,我又如何实例化它呢?其实我们可以这样子做:(这种是经典的单件模式实现)
public class Singleton {
private static Singleton uniqueInstance;//利用一个静态变量来记录Singleton类的唯一实例
// other useful instance variables here
private Singleton() {}//只有自己才能调用构造器
public static Singleton getInstance() {
//断点1(为下面文字解析使用)
if (uniqueInstance == null) {
//断点2
uniqueInstance = new Singleton();//当uniqueInstance不存在时才创建
}
return uniqueInstance;
}
// other useful methods here
}
如果你以为这样已经完美了,那就太天真了。在一个单线程中运行,这样确实已经完美了,但如果有很多个线程并发的情况下,那单件可能就不是单件了。
如:现在有两个线程A和B,当单件类还没实例化时,A和B线程都执行到断点1,因为单件类还没实例化,所以都可以执行断点2,当A这时先实例化单件类,虽然这时已经实例化单件类了,但这时已经不能阻止线程B再次执行实例化了(因为这时B已经进来了),这时就存在2个实例了,所以这种经典的单件模式实现有点瑕疵。
对于如何处理多线程的问题,我这有三种解决方法。
第一种:
public class Singleton {
private static Singleton uniqueInstance;
// other useful instance variables here
private Singleton() {}
public static synchronized Singleton getInstance() {//比上面的代码中多了一个synchronized
if (uniqueInstance == null) {
uniqueInstance = new Singleton();
}
return uniqueInstance;
}
// other useful methods here
}
没错,就是加线程锁来解决,要求进入getInstance()方法前,要等候别的线程离开该方法,才能执行,就是所不存在两个或以上的线程同时进入这个方法。但其实我们只有第一次执行此方法时才真正需要同步,创建好uniqueInstance变量后,我们就不需要同步这个方法了,而同步会降低性能,是一种累赘。
第二种:
public class Singleton {
//在静态初始化器中创建单件,保证了线程安全
private static Singleton uniqueInstance = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return uniqueInstance;
}
}
这种就是一开始就创建好单件类,而不用延迟实例化的做法,如果创建和运行这个单件类时,负担不太繁重,就可以利用这种方法创建单件,毕竟简单好用嘛。
第三种:(我认为最好的一种,不过需要java 5及以上版本才能使用)
public class Singleton {
private volatile static Singleton uniqueInstance;
private Singleton() {}
public static Singleton getInstance() {
//断点1
if (uniqueInstance == null) {
//断点2
synchronized (Singleton.class) {
//断点3
if (uniqueInstance == null) {
//断点4
uniqueInstance = new Singleton();
}
}
}
return uniqueInstance;
}
}
首先解析volatile这个是有什么用的:用在多线程,同步变量。 线程为了提高效率,将某成员变量(如A)拷贝了一份(如B),线程中对A的访问其实访问的是B。只在某些动作时才进行A和B的同步。因此存在A和B不一致的情况。volatile就是用来避免这种情况的。volatile告诉jvm, 它所修饰的变量不保留拷贝,直接访问主内存中的(也就是上面说的A) ,但不保证原子操作。
还是以两个线程A和B来说明,当单件类还没实例化时,线程A和B同时执行到断点1,判断完之后就会执行到断点2,这时假设A先快一步,执行到断点3并锁住类,线程B只能等待,线程A判断完后,执行断点4并实例化单件类后,离开方法解锁;线程B执行到断点3并锁住类,这时判断实例uniqueInstance已存在,离开并解锁。后面其他一些线程只会执行到断点1,并不会执行到断点2,这样就避免了线程锁所带来的性能问题了。
注意锁前锁后的判断都是必须的,锁前是避免创建实例后其他线程执行线程锁方法,提高了性能;锁后,是避免创建多个实例,不然有多少个线程进入断点2,就会产生多少个实例。
这就是“双重检查加锁”的方法。
这就是单件模式,如果对其他的一些设计模式也感兴趣,欢迎查看我其他的一些博客。
转载请标明原文出处:http://blog.csdn.net/u012367513/article/details/31037887
分享到:
相关推荐
### 深入浅出设计模式之单件模式 #### 一、单件模式概述 单件模式(Singleton Pattern)是软件设计模式中最为常见的一种,它的主要目标是确保某个类只有一个实例,并提供一个全局访问点。单件模式在很多情况下都...
单件模式(Singleton Pattern)是设计模式中的一种,它的核心意图是确保一个类只有一个实例,并提供一个全局访问点。在软件工程中,这样的设计模式能够有效地控制资源的使用,限制实例的数量,以及协调对象间的交互...
**单例模式(Singleton)**是软件设计模式中的一种创建型模式,它的核心思想是确保一个类只有一个实例,并提供一个全局访问点。这种模式在很多场景下非常有用,例如管理共享资源、配置对象或者数据库连接等。单例...
"设计模式-单件模式" 单件模式是指确保整个应用程序中只有一个类实例且这个实例所占资源在整个应用程序中是共享的程序设计方法。单件模式是一种非常实用的设计模式,它可以控制一个类的实例数量,使得调用者可以从...
本文将深入探讨四种常见的设计模式:单件模式(Singleton)、工厂模式(Factory)、策略模式(Strategy)和观察者模式(Observer),并以PHP语言为背景进行解释。 首先,我们来看单件模式。单件模式确保一个类只有...
### 设计模式——工厂模式与单例模式 #### 一、引言 设计模式是软件工程领域中的一个重要概念,它代表了在特定情况下解决常见问题的最佳实践。在本篇文章中,我们将深入探讨两种广泛使用的软件设计模式:工厂模式...
单件模式(Singleton Pattern)是软件设计模式中的一种经典模式,它的主要目的是确保一个类只有一个实例,并提供一个全局访问点。这种模式在很多场景下非常有用,比如配置管理、线程池、数据库连接等需要全局唯一的...
C#作为.NET框架的主要编程语言,广泛应用于各种复杂系统开发,其中单件模式(Singleton Pattern)是C#开发者经常会遇到的一种设计模式。本资源旨在帮助初学者理解并应用单件模式,通过关键代码实例,让你快速掌握这...
单件模式(Singleton Pattern)是一种常见的软件设计模式,它的核心思想是确保一个类只有一个实例,并提供一个全局访问点。在JavaScript中,虽然由于其动态特性和运行环境的原因,单件模式的应用不如Java或C#等...
单件模式(Singleton Pattern)是软件设计模式中的一种基础模式,它确保一个类只有一个实例,并提供一个全局访问点。在C#中,单例模式的实现有多种方式,包括懒汉式、饿汉式以及线程安全的实现。下面我们将详细讨论...
在编程中,设计模式是一种在特定情境下解决常见问题的标准化解决方案,其中“单件(Singleton)”设计模式是被广泛应用的一种。单件模式确保一个类只有一个实例,并提供一个全局访问点,这样在整个程序中可以统一...
单件模式(Singleton pattern)是设计模式中的一种结构型模式,它的主要目的是确保一个类只有一个实例,并提供一个全局访问点。这种模式常用于系统中需要频繁创建和销毁的对象,如日志服务、线程池或者数据库连接等...
李建忠面向对象设计模式视频精讲:Singleton 单件(创建型模式)
单实例模式是软件设计模式中的一种,它的核心思想是确保一个类在整个系统运行过程中只有一个实例存在,并提供一个全局访问点,以保证所有对该类对象的访问都指向这个唯一的实例。这种模式在Java中广泛应用于配置管理...
在C#编程中,面向对象设计模式是一种组织代码和解决常见设计问题的模板。Singleton模式是一种创建型设计模式,它确保一个类只有一个实例,并提供一个全局访问点来获取这个唯一的实例。这种模式在需要控制资源的唯一...
设计模式之 Singleton(单态/单件) 阎宏博士讲解:单例(Singleton)模式 保证一个类只有一个实例,并提供一个访问它的全局访问点 设计模式之 Factory(工厂方法和抽象工厂) 使用工厂模式就象使用 new 一样频繁. ...
单件模式(Singleton Pattern)是设计模式中的一种,它的主要目的是确保一个类只有一个实例,并提供一个全局访问点。这种模式在软件开发中被广泛应用,比如配置管理、数据库连接池、日志服务等场景,需要确保全系统...