Java 多线程编程中单例的实现

对于普通单线程单例来说,较为容易,只要避免创建多个对象即可,代码如下:

public class Singleton {
      private static Singleton singleton = null;
      public static Singleton getInstance(){
          if(singleton==null){
                   singleton = new Singleton();
          }
          return singleton;
      }
}

这样既可以避免创建多个对象消耗系统资源,也可以达到惰性加载,即在使用时才会创建对象;

在单线程时,该类可以很完美的解决单例问题,但是到了多线程,该类将会出现问题:

当两个现成A和B 同时调用单例获得实例时,若A进入getInstance()方法,判断当前singleton为空,则进入singleton=new Singeton(),并返回singleton,但是当A进入时,B同时调用,B也会判断singleton为空,因为A进入后并没有初始化完成,所以B同样会进入初始化代码,进行初始化并返回singleton,这样就出现问题了,并没有实现单例操作。

所以在多线程环境下,我们需要对该代码进行一点修改,那就是给getInstance方法加上同步锁,使A和B不能同时进入该方法内,代码如下:

public class Singleton {
      private static Singleton singleton = null;
      public static synchronized Singleton getInstance(){
          if(singleton==null){
                   singleton = new Singleton();
          }
          return singleton;
      }
}

经过修改后,我们发现在出现之前A和B 同时访问getInstance方法时,若A先进入getInstance方法,由于sychronized的存在,B是不可能进入该方法的,会在A线程执行完成之前将该方法进行加锁操作,执行完成之后才会允许B进入该方法,而当B进入方法时,singleton已经不再是null,直接返回单例singleton对象;

但是实际上,若多个线程调用时,同步锁的存在,很大程度上影响程序性能,所以后来有人提出double-checked blocking方法,来降低性能影响:

还有一种方法,叫做double-check blocking,代码如下:

public class Singleton {
      private static Singleton singleton = null;
      public static Singleton getInstance(){
          if(singleton==null){
                 synchronized (singleton){
                      if(singleton==null){
                           singleton = new Singleton();
                        }
                  }
          }
          return singleton;
      }
}

经过此次修改,当线程进入getInstance方法后,将会先判断singleton是否为空,这样减少了进入同步块所花费的资源,降低了资源消耗,提高了性能,

似乎这样修改以后,即不会造成同步锁消耗资源,也不会由于多线程同时进入创建多个对象,但是,实际上,从更深一层来讲,站在jvm的层面来说,这样的代码仍可能发生问题:

由于在执行singleton = new Singleton();时,jvm是分两步进行的,先是为singleton预留空间,直接赋值给instance,然后才会初始化singleton,创建singleton实例,

如果A先进入singleton = new sSingleton(),但是只是分配了空间,并没有初始化完成,就返回singleton,那么当B线程进入时,singleton已经不为null,那么将直接返回已有的singleton,若在singleton真正初始化之前就使用的话,问题就来了,所有 多线程单例模式,又出现了新的解决办法:

public class Singleton{
     private static c lass SingletonContainer{
             private static Singleton instance = new Singleton();
     }
     public static Singleton getInstance(){
            return SingletonContainer.instance;
     }

}

  该方法为通过内部类实现多线程环境中的单例,

JVM内部机制能够保证当一个类被加载时,这个类的加载过程是线程安全的,当我们第一次调用getInstance方法时,JVM能够保证instance只被创建一次,并且保证初始化完成,这样我们就不再需要担心instance没有被创建完成了,同时实现了惰性加载单例

时间: 2024-10-12 16:33:42

Java 多线程编程中单例的实现的相关文章

Java多线程编程6--单例模式与多线程--单例模式

单例对象(Singleton)是一种常用的设计模式.在Java应用中,单例对象能保证在一个JVM中,该对象只有一个实例存在.这样的模式有几个好处: 1.)某些类创建比较频繁,对于一些大型的对象,这是一笔很大的系统开销. 2.)省去了new操作符,降低了系统内存的使用频率,减轻GC压力. 3.)有些类如交易所的核心交易引擎,控制着交易流程,如果该类可以创建多个的话,系统完全乱了.(比如一个军队出现了多个司令员同时指挥,肯定会乱成一团),所以只有使用单例模式,才能保证核心交易服务器独立控制整个流程.

Java多线程编程6--单例模式与多线程--单例模式设计详解1

在标准的23个设计模式中,单例设计模式在应用中是比较常见的.但在常规的该模式教学资料介绍中,多数并没有结合多线程技术作为参考,这就造成在使用多线程技术的单例模式时会出现一些意想不到的情况,这样的代码如果在生产环境中出现异常,有可能造成灾难性的后果. 1.立即加载/"饿汉模式" 什么是立即加载?立即加载也称为"饿汉模式",就是使用类的时候已经将对象创建完毕,常见的实现办法就是直接new实例化. 立即加载/"饿汉模式"是在调用方法前,实例已经被创建了

Java多线程编程6--单例模式与多线程--使用静态内置类、(反)序列化、static代码块、enum枚举数据类实现

前面讲的用DCL可以解决多线程单例模式的非线程安全,虽然看下去十分完美,但还是有一些问题,具体分析看这篇:http://blog.csdn.net/ochangwen/article/details/51348078 当然用其他的办法也能达到同样的效果. 1.使用静态内置类实现单例模式 public class Singleton { /* 私有构造方法,防止被实例化 */ private Singleton() { } /* 此处使用一个内部类来维护单例 */ private static c

Java 多线程编程两个简单的样例

/** * @author gao */ package gao.org; public class RunnableDemo implements Runnable{ @Override public void run() { // TODO Auto-generated method stub for(int i=0;i<10;i++){ System.out.println("新线程输出:"+i); } } public static void main(String []

java多线程编程

一.多线程的优缺点 多线程的优点: 1)资源利用率更好2)程序设计在某些情况下更简单3)程序响应更快 多线程的代价: 1)设计更复杂虽然有一些多线程应用程序比单线程的应用程序要简单,但其他的一般都更复杂.在多线程访问共享数据的时候,这部分代码需要特别的注意.线程之间的交互往往非常复杂.不正确的线程同步产生的错误非常难以被发现,并且重现以修复. 2)上下文切换的开销当CPU从执行一个线程切换到执行另外一个线程的时候,它需要先存储当前线程的本地的数据,程序指针等,然后载入另一个线程的本地数据,程序指

Java多线程编程详解

线程的同步 由于同一进程的多个线程共享同一片存储空间,在带来方便的同时,也带来了访问冲突这个严重的问题.Java语言提供了专门机制以解决这种冲突,有效避免了同一个数据对象被多个线程同时访问. 由于我们可以通过 private 关键字来保证数据对象只能被方法访问,所以我们只需针对方法提出一套机制,这套机制就是 synchronized 关键字,它包括两种用法:synchronized 方法和 synchronized 块. 1. synchronized 方法:通过在方法声明中加入 synch

Java多线程编程中Future模式的详解&lt;转&gt;

Java多线程编程中,常用的多线程设计模式包括:Future模式.Master-Worker模式.Guarded Suspeionsion模式.不变模式和生产者-消费者模式等.这篇文章主要讲述Future模式,关于其他多线程设计模式的地址如下:关于其他多线程设计模式的地址如下:关于Master-Worker模式的详解: Java多线程编程中Master-Worker模式的详解关于Guarded Suspeionsion模式的详解: Java多线程编程中Guarded Suspeionsion模式

JAVA读书推荐----《深入分析Java Web技术内幕》--《java多线程编程核心技术》--《大型网站技术架构 核心原理与案例分析》-《Effective Java中文版》

(1)  首先推荐的不是一本书,而是一个博客,也是我们博客园另外一位博友java_my_life. 目前市面上讲解设计模式的书很多,虽然我前面讲了看书是最好的,但是对设计模式感兴趣的朋友们,我推荐的是这个博客.这位博友的设计模式讲得非常非常好,我认为90%的内容都是没有问题且很值得学习的,其讲解设计模式的大体路线是: 1.随便开篇点明该设计模式的定义 2.图文并茂讲解该设计模式中的结构 3.以详细的代码形式写一下该种设计模式的实现 4.补充内容 5.讲解该设计模式的优缺点 对于一个设计模式我们关

《Java多线程编程核心技术》推荐

写这篇博客主要是给猿友们推荐一本书<Java多线程编程核心技术>. 之所以要推荐它,主要因为这本书写得十分通俗易懂,以实例贯穿整本书,使得原本抽象的概念,理解起来不再抽象. 只要你有一点点Java基础,你就可以尝试去阅读它,相信定会收获甚大! 博主之前网上找了很久都没完整pdf电子版的,只有不全的试读版,这里博主提供免费.清晰.完整版供各位猿友下载: http://download.csdn.net/detail/u013142781/9452683 刚刚已经提到,<Java多线程编程核