1、时间和空间效率
比较上面两种写法:懒汉式是典型的时间换空间,也就是每次获取实例都会进行判断,看是否需要创建实例,浪费判断的时间。当然,如果一直没有人使用的话,那就不会创建实例,则节约内存空间。
饿汉式是典型的空间换时间,当类装载的时候就会创建类实例,不管你用不用,先创建出来,然后每次调用的时候,就不需要再判断了,节省了运行时间。
2、线程安全
(1)从线程安全性上讲,不加同步的懒汉式是线程不安全的,比如,有两个线程,一个是线程A,一个是线程B,它们同时调用getInstance方法,那就可能导致并发问题。如下示例:
public static Singleton getInstance(){
if(instance == null){
instance = new Singleton();
}
return instance;
}
假如出现这样一种情况,如下图:
明显地看出,当A、B线程并发的情况下,有可能会创建出两个实例来,也就是单例的控制在并发情况下失效了。
(2)饿汉式是线程安全的,因为虚拟机保证只会装载一次,在装载类的时候是不会发生并发的。
(3)如何让懒汉式实现线程安全呢?
当然懒汉式也是可以实现线程安全的,只要加上synchronized即可,如下:
publicstaticsynchronizedSingletongetInstance(){}
但是这样一来,会降低整个访问的速度,而且每次都要判断。那么有没有更好的方式来实现呢?
(4)双重检查加锁
可以使用"双重检查加锁"的方式来实现,就可以既实现线程安全,又能够使性能不受到很大的影响。那么什么是"双重检查加锁"机制呢?
所谓双重检查加锁机制,指的是:并不是每次进入getInstance方法都需要同步,而是先不同步,进入方法过后,先检查实例是否存在,如果不存在才进入下面的同步块,这是第一重检查。进入同步块过后,再次检查实例是否存在,如果不存在,就在同步的情况下创建一个实例,这是第二重检查。这样一来,就只需要同步一次了,从而减少了多次在同步情况下进行判断所浪费的时间。
双重检查加锁机制的实现会使用一个关键字volatile,它的意思是:被volatile修饰的变量的值,将不会被本地线程缓存,所有对该变量的读写都是直接操作共享内存,从而确保多个线程能正确的处理该变量。
看看代码可能会更加清楚些。示例代码如下:
public class Singleton {
/**
* 对保存实例的变量添加volatile的修饰
*/
private volatile static Singleton instance = null;
private Singleton(){
}
public static Singleton getInstance(){
//先检查实例是否存在,如果不存在才进入下面的同步块
if(instance == null){
//同步块,线程安全地创建实例
synchronized(Singleton.class){
//再次检查实例是否存在,如果不存在才真正地创建实例
if(instance == null){
instance = new Singleton();
}
}
}
return instance;
}
}
这种实现方式可以实现既线程安全地创建实例,而又不会对性能造成太大的影响。它只是在第一次创建实例的时候同步,以后就不需要同步了,从而加快了运行速度。
原文链接地址:单例模式的优缺点http://book.51cto.com/art/201010/232020.htm
分享到:
相关推荐
单例设计模式是一种在软件工程中广泛使用的设计模式,它的主要目标是确保一个类只有一个实例,并提供一个全局访问点。...通过阅读《单例设计模式.pdf》文档,你可以更全面地了解单例模式的各种实现方式和应用场景。
以下是几种常见的单例模式实现方式: 1. **饿汉式(静态常量)**: 这是最简单的实现方式,它在类加载时就完成了初始化,因此是线程安全的。 ```java public class Singleton { private static final Singleton...
在这个例子中,`Emperor` 类通过私有化构造函数和提供一个静态方法 `getInstance()` 来实现单例模式,确保了无论何时调用 `getInstance()` 方法,返回的总是同一个 `Emperor` 实例,从而实现了“皇帝只有一个”的...
以上就是Java中实现单例模式的常见方法,每种方式都有其适用场景和优缺点。在实际开发中,我们需要根据项目需求选择合适的方式实现单例。同时,理解单例模式背后的原理和应用场景,有助于提升代码的设计质量。
总结起来,Java中的单例模式有多种实现,每种都有其优缺点。开发者应根据项目需求选择适合的实现方式,比如对性能要求较高的场景可以选择静态内部类或枚举,而对内存占用敏感的场景则可能更适合饿汉式。通过学习和...
下面将详细介绍七种常见的单例模式实现方式,并结合多线程环境和反序列化测试进行讨论。 1. **饿汉式单例**: 这是最简单的单例实现,它在类加载时就创建了实例,因此是线程安全的。 ```java public class ...
### 三、单例模式的应用场景与优缺点 **应用场景**: - 全局日志对象 - 数据库连接池 - 缓存服务 - 线程池 - 多线程环境下的线程同步控制 **优点**: - 节省内存空间,减少系统资源消耗。 - 避免对资源的多重占用...
在给定的内容中提到的`Martin`类就是一个典型的单例模式实现案例。它通过将构造器私有化以及提供一个静态成员变量来确保了`Martin`类的唯一实例的存在。 ```java public class Martin { private Martin() { // ...
单例模式是软件设计模式中...在实际开发中,应根据项目需求和环境选择合适的单例模式实现。在设计模式中,单例模式不仅限于上述实现,还可以与其他模式结合使用,如工厂模式、装饰器模式等,以达到更灵活、高效的设计。
单例模式的优缺点: **优点:** - **全局访问点**:可以方便地在程序的任何地方访问单例对象,提高代码的可读性和可维护性。 - **资源控制**:单例可以用于管理和控制有限的系统资源,如数据库连接、网络请求等。 -...
每种实现方式都有其优缺点,选择哪种方式取决于具体的应用场景。例如,如果对性能要求较高,可以考虑DCL或静态内部类;如果代码简洁性更重要,枚举方式可能是最佳选择。在实际应用中,应根据项目需求来决定采用哪种...
#### 三、单例模式的创建方式及优缺点 单例模式的实现方式主要有三种:饿汉式、懒汉式以及静态内部类方式。 - **饿汉式** - **实现**: ```java public class Single1 { // 创建一个静态的实例 private ...
在C++中,实现单例模式有多种方法,我们将会深入探讨这一模式的原理、优缺点以及如何在实际编程中应用。 单例模式的核心在于控制类的实例化过程,防止多处代码创建多个实例导致资源的浪费或者状态不一致的问题。在...
在ACCP V4.0的讲解中,提到了五种不同的单例模式实现方式: 1. **简单实现**: 这是最基础的实现方式,通过私有的构造函数防止外部直接实例化,然后通过静态的`getInstance()`方法返回唯一的实例。但是这种方式在...
以上就是Java中实现单例模式的五种常见方法,每种方法都有其优缺点。在实际开发中,根据项目需求和性能考虑,选择合适的方式实现单例模式。同时,随着Java技术的发展,枚举单例、基于依赖注入的单例等新型实现方式也...
下面是一个简单的单例模式实现示例: ```objective-c @interface Singleton : NSObject + (instancetype)sharedSingleton; @end @implementation Singleton static Singleton *sharedInstance = nil; + ...
Java中实现单例模式的方法有很多种,每种方法都有其适用场景和优缺点。选择合适的实现方式需要根据实际需求和应用场景综合考虑。例如,如果程序启动时就需要单例对象,那么可以使用饿汉式;如果希望在真正需要时才...
Java单例模式及实现 Java单例模式是一种常见的设计模式,确保某一个类只有一个实例,而且向这个系统提供这个实例。单例模式可以分为三种:懒汉式单例、...每种方式都有其优缺点,需要根据具体情况选择合适的实现方式。
在Java中,常见的单例模式实现方式有以下几种: 1. 饿汉式(静态常量): 这种实现方式在类加载时就完成了初始化,所以是线程安全的。代码如下: ```java public class Singleton { private static final ...