`
yinwufeng
  • 浏览: 286967 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

java Singleton 的使用详解

 
阅读更多

概念:

在Java应用程序中,一个类Class只有一个实例存在

运用:

1)系统资源,如文件路径,数据库链接,系统常量等

2)全局状态化类,类似AutomicInteger的使用

优缺点:

1)节省内存有利于垃圾回收

2)只能使用在特定的环境下,受限制于JVM和容器

     单例作用范围的前提是在一个ClassLoad下。所以像分布式应用EJB就要用其它的方式来解决单例问题。

Demo:

分别列出多种实现方式,各分析其优缺点

1)静态成员直接初始化,或者在静态代码块初始化都可以

Java代码  收藏代码
  1. class Singleton{    
  2.     private Singleton(){}    
  3.     private static final Singleton singleton = new Singleton();    
  4.     public static Singleton getInstance(){return singleton;}    
  5. }    
 

      该实现只要在一个ClassLoad下就会提供一个对象的单例。但是美中不足的是,不管该资源是否被请求,它都会创建一个对象,占用jvm内存。从lazy initialization思想出发,出现了下2的写法

2)根据lazy initialization思想,使用到时才初始化。

Java代码  收藏代码
  1. class Singleton{    
  2.     private Singleton(){}    
  3.     private static Singleton singleton ;    
  4.     public static synchronized Singleton getInstance(){    
  5.         if(singleton==null)    
  6.             singleton = new Singleton();    
  7.         return singleton;           
  8.     }       
  9. }    
 

       该实现方法加了同步锁,可以有效防止多线程在执行getInstance方法得到2个对象。

缺点:只有在第一次调用的时候,才会出现生成2个对象,才必须要求同步。而一旦singleton 不为null,系统依旧花费同步锁开销,有点得不偿失。

因此再改进出现写法3

3)在2的基础上改进,改进标准:尽量减少锁资源(主要体现在执行时间,所占内存等)

Java代码  收藏代码
  1. class Singleton{    
  2.     private Singleton(){}    
  3.     private static Singleton singleton ;    
  4.     public static Singleton getInstance(){    
  5.         if(singleton==null)//1    
  6.             synchronized(Singleton.class){//2    
  7.                 singleton = new Singleton();//3    
  8.             }    
  9.         return singleton;           
  10.     }       
  11. }    
 

这种写法减少了锁开销,但是在如下情况,却创建了2个对象:

a:线程1执行到1挂起,线程1认为singleton为null

b:线程2执行到1挂起,线程2认为singleton为null

c:线程1被唤醒执行synchronized块代码,走完创建了一个对象

d:线程2被唤醒执行synchronized块代码,走完创建了另一个对象

所以看出这种写法,并不完美。

4)为了解决3存在的问题,引入双重检查锁定

Java代码  收藏代码
  1. public static Singleton getInstance(){    
  2.         if(singleton==null)//1    
  3.             synchronized(Singleton.class){//2    
  4.                 if(singleton==null)//3    
  5.                     singleton = new Singleton();//4    
  6.             }    
  7.         return singleton;           
  8.     }    
 

      在同步锁代码块内部,再判断一次对象是否为null,为null才创建对象。这种写法已经接近完美:

a:线程1执行到1,已经进入synchronized的时候,线程挂起,线程1占有Singleton.class资源锁;

b:线程2执行到1,当它准备synchronized块时,因为Singleton.class被占用,线程2阻塞;

c:线程1被唤醒,判断出对象为null,执行完创建一个对象

d:线程2被唤醒,判断出对象不为null,不执行创建语句

      如此分析,发现似乎没问题。

      但是实际上并不能保证它在单处理器或多处理器上正确运行;

      问题就出现在singleton = new Singleton()这一行代码。它可以简单的分成如下三个步骤:

mem= singleton();//1

instance = mem;//2

ctorSingleton(instance);//3

       这行代码先在内存开辟空间,赋给singleton的引用,然后执行new 初始化数据,但是注意初始化是要消耗时间。如果此时线程3在执行步骤1的时候,发现singleton 为非null,就直接返回,那么线程3返回的其实是一个没构造完成的对象。

      我们期望1,2,3 按照反序执行,但是实际jvm内存模型,并没有明确的有序指定。

      这归咎于java的平台的内存模型允许“无序写入”。

5)在4的基础上引入volatile

代码如下:

 

 

Java代码  收藏代码
  1. class Singleton{    
  2.     private Singleton(){}    
  3.     private static volatile Singleton singleton ;    
  4.     public static Singleton getInstance(){    
  5.         if(singleton==null)//1    
  6.             synchronized(Singleton.class){//2    
  7.                 if(singleton==null)//3    
  8.                     singleton = new Singleton();    
  9.             }    
  10.         return singleton;           
  11.     }       
  12. }    
 

       Volatile 变量具有 synchronized 的可见性特性,但是不具备原子特性。这就是说线程能够自动发现 volatile 变量的最新值。

而volatile使用时有明确的规定:

  1.       对变量的写操作不依赖于当前值;
  2.       该变量没有包含在具有其他变量的不变式中;

—— 只有在状态真正独立于程序内其他内容时才能使用 volatile。

但是5的写法,虽然理论上似乎可以解决无序写入问题。实际上并非如此。

(我个人觉得这里对volatile语法说的不够详细,想知道详细的可以看这篇转帖Java 理论与实践: 正确使用 Volatile 变量 

小结:

1)使用同步锁方法,内部锁存在不安全。

2)静态成员直接初始化。

 

分享到:
评论

相关推荐

    Java的Singleton模式代码(免资源分)

    ### Java的Singleton模式详解 #### 一、Singleton模式概述 Singleton模式是一种常用的设计模式,在Java中主要用于确保一个类只有一个实例,并提供一个全局访问点。这种模式对于管理共享资源(如数据库连接池、...

    Java2编程详解

    Java2编程详解是一个专注于Java编程语言的深入教程,适用于不同经验水平的程序员。从初级开发到高级开发,本书旨在为读者提供全面的知识体系,帮助他们不仅学习Java的基础知识,更能够掌握并应用多种常用的开发模式...

    设计模式JAVA版本代码详解

    在Java中,可以使用双重检查锁定(DCL)、枚举和静态内部类等方式实现。单例模式常用于配置中心、缓存管理等场景。 2. **工厂模式(Factory Method)**:定义一个创建对象的接口,但让子类决定实例化哪一个类。工厂...

    java单例模式详解

    为了保证线程安全,通常使用`synchronized`关键字对方法进行同步,但这样会降低性能。代码如下: ```java public class Singleton { private static Singleton INSTANCE; private Singleton() {} public ...

    java设计模式详解,java design pattern

    Java设计模式详解涉及到23种设计模式,这些设计模式可以根据其目的和范围被划分为三大类:创建型模式(Creational Patterns)、结构型模式(Structural Patterns)和行为型模式(Behavioral Patterns)。下面将详细...

    java23种设计模式详解+源码(绝对详解)

    在Java编程中,有23种经典的GoF(Gang of Four)设计模式,它们被分为三大类:创建型、结构型和行为型。本资源集合了这些模式的详细解释与源码分析,旨在帮助开发者深入理解和应用设计模式。 1. 创建型模式...

    Java设计模式详解

    1. 创建型模式:如单例模式(Singleton)、工厂模式(Factory Method)和抽象工厂模式(Abstract Factory),主要关注对象的创建过程,使得代码更易于管理和测试。 2. 结构型模式:如适配器模式(Adapter)、装饰器...

    Java的23种设计模式详解

    在Java中,可以使用双重检查锁定(Double-Checked Locking)或者静态内部类方式实现。 2. **工厂模式(Factory)**:定义一个创建对象的接口,但让子类决定实例化哪一个类。工厂方法让类的实例化推迟到子类。 3. *...

    java24种设计模式详解

    设计模式是软件工程中的一种最佳实践,它是在特定上下文中解决常见问题的模板或蓝图。...在"java24种设计模式详解"这个资源中,你会找到每种模式的详细讲解和实例,这将有助于你深入理解并掌握它们。

    java设计模式详解ppt

    创建型模式如单例(Singleton)、工厂方法(Factory Method)和抽象工厂(Abstract Factory),主要关注对象的创建过程,确保在适当的时间以适当的方式创建对象。结构型模式如适配器(Adapter)、装饰器(Decorator...

    Java设计模式-图文详解

    ### Java设计模式详解 #### 1. 创建型模式 创建型模式主要关注的是对象的创建方式,它们提供了创建对象的最佳方法。以下是对几种常见的创建型模式的深入解析: ##### 1.1.1 工厂方法(Factory Method) **定义**...

    高阶Java-Java枚举类型 enum 应用详解

    在Java编程语言中,枚举(enum)是一种特殊的类,用于定义一组固定的常量。它在许多场景下比使用常量或int类型的硬编码值更安全、更具可读性。本篇文章将深入探讨Java枚举的特性、用法以及如何在实际开发中充分利用...

    Java中23种设计模式详解

    Java 中 23 种设计模式详解 在软件设计中,设计模式是解决特定问题的通用解决方案。 Java 中有 23 种常见的设计模式,下面将对每种设计模式进行详细的解释: 1. 抽象工厂模式(Abstract Factory) 抽象工厂模式...

    Java设计模式-单例模式详解

    Java设计模式-单例模式详解 单例模式是 Java 设计模式中的一种常用的设计模式,旨在保证一个类仅有一个实例,并提供一个访问它的全局访问点。单例模式的目的是为了保证在一个进程中,某个类有且仅有一个实例。 ...

    Java软件开发实战 Java基础与案例开发详解 6-5 static修饰符 共13页.pdf

    ### Java软件开发实战:Java基础与案例开发详解之Static修饰符 #### 6.5 Static修饰符 在Java中,`static`关键字用于声明与类而不是与实例相关的变量、方法或代码块。这一特性使得静态成员能够被类本身直接访问,...

    Singleton pattern单例模式应用

    ### Singleton Pattern 单例模式应用详解 #### 一、单例模式概述 单例模式(Singleton Pattern)是一种常用的软件设计模式,在系统中确保某个类只有一个实例,并提供一个全局访问点。这种模式通常用于控制资源的...

    9种Java单例模式详解(推荐)

    Java单例模式详解 Java单例模式是Java编程中的一种设计模式,旨在保证一个类仅有一个实例,并提供一个全局访问点。下面我们将对9种Java单例模式进行详细的介绍。 首先,单例模式的特点是: 1. 一个类只允许产生...

    Singleton 单件(创建型模式)

    **Singleton 模式详解** Singleton 是一种在软件工程中广泛使用的创建型设计模式,它的主要目的是确保一个类只有一个实例,并提供一个全局访问点。这种模式常用于需要频繁实例化然后销毁的对象,或者当实例化一个...

    五种单件模式之Singleton的实现方法详解

    在Java中,实现Singleton有许多方法,每种都有其优缺点。以下是五种常见的Singleton实现方法的详细解析: 1. **基本实现(非线程安全)** ```java public class Singleton1 { private static Singleton1 ...

Global site tag (gtag.js) - Google Analytics