java单例模式详解[转载]

概念:
  java中单例模式是一种常见的设计模式,单例模式分三种:懒汉式单例、饿汉式单例、登记式单例三种。
  单例模式有一下特点:
  1、单例类只能有一个实例。
  2、单例类必须自己自己创建自己的唯一实例。
  3、单例类必须给所有其他对象提供这一实例。
  单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。在计算机系统中,线程池、缓存、日志对象、对话框、打印机、显卡的驱动程序对象常被设计成单例。这些应用都或多或少具有资源管理器的功能。每台计算机可以有若干个打印机,但只能有一个Printer Spooler,以避免两个打印作业同时输出到打印机中。每台计算机可以有若干通信端口,系统应当集中管理这些通信端口,以避免一个通信端口同时被两个请求同时调用。总之,选择单例模式就是为了避免不一致状态,避免政出多头。

首先看一个经典的单例实现。

public class Singleton {

private static Singleton uniqueInstance = null;

private Singleton() {

// Exists only to defeat instantiation.

}

public static Singleton getInstance() {

if (uniqueInstance == null) {

uniqueInstance = new Singleton();

}

return uniqueInstance;

}

// Other methods...

}

Singleton通过将构造方法限定为private避免了类在外部被实例化,在同一个虚拟机范围内,Singleton的唯一实例只能通过getInstance()方法访问。(事实上,通过Java反射机制是能够实例化构造方法为private的类的,那基本上会使所有的Java单例实现失效。此问题在此处不做讨论,姑且掩耳盗铃地认为反射机制不存在。)

但是以上实现没有考虑线程安全问题。所谓线程安全是指:如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。或者说:一个类或者程序所提供的接口对于线程来说是原子操作或者多个线程之间的切换不会导致该接口的执行结果存在二义性,也就是说我们不用考虑同步的问题。显然以上实现并不满足线程安全的要求,在并发环境下很可能出现多个Singleton实例。

 1 public class TestStream { 2     private String name; 3     public String getName() { 4         return name; 5     } 6     public void setName(String name) { 7         this.name = name; 8     }  9     //该类只能有一个实例10     private TestStream(){}    //私有无参构造方法11     //该类必须自行创建12     //有2种方式13     /*private static final TestStream ts=new TestStream();*/14     private static TestStream ts1=null;15     //这个类必须自动向整个系统提供这个实例对象16     public static TestStream getTest(){17         if(ts1==null){18             ts1=new TestStream();19         }20         return ts1;21     }22     public void getInfo(){23         System.out.println("output message "+name);24     }25 }

 1 public class TestMain { 2     public static void main(String [] args){ 3         TestStream s=TestStream.getTest(); 4         s.setName("张孝祥"); 5         System.out.println(s.getName()); 6         TestStream s1=TestStream.getTest(); 7         s1.setName("张孝祥"); 8         System.out.println(s1.getName()); 9         s.getInfo();10         s1.getInfo();11         if(s==s1){12             System.out.println("创建的是同一个实例");13         }else if(s!=s1){14             System.out.println("创建的不是同一个实例");15         }else{16             System.out.println("application error");17         }18     }19 }

运行结果:
  张孝祥
  张孝祥
  output message 张孝祥
  output message 张孝祥
  创建的是同一个实例

结论:由结果可以得知单例模式为一个面向对象的应用程序提供了对象惟一的访问点,不管它实现何种功能,整个应用程序都会同享一个实例对象。

1.饿汉式单例类

 1 //饿汉式单例类.在类初始化时,已经自行实例化  2 public class Singleton1 { 3     //私有的默认构造子 4     private Singleton1() {} 5     //已经自行实例化  6     private static final Singleton1 single = new Singleton1(); 7     //静态工厂方法  8     public static Singleton1 getInstance() { 9         return single;10     }11 }

2.懒汉式单例类

 1 //懒汉式单例类.在第一次调用的时候实例化  2 public class Singleton2 { 3     //私有的默认构造子 4     private Singleton2() {} 5     //注意,这里没有final     6     private static Singleton2 single=null; 7     //静态工厂方法  8     public synchronized  static Singleton2 getInstance() { 9          if (single == null) {  10              single = new Singleton2();11          }  12         return single;13     }14 }

3.登记式单例类

 1 import java.util.HashMap; 2 import java.util.Map; 3 //登记式单例类. 4 //类似Spring里面的方法,将类名注册,下次从里面直接获取。 5 public class Singleton3 { 6     private static Map<String,Singleton3> map = new HashMap<String,Singleton3>(); 7     static{ 8         Singleton3 single = new Singleton3(); 9         map.put(single.getClass().getName(), single);10     }11     //保护的默认构造子12     protected Singleton3(){}13     //静态工厂方法,返还此类惟一的实例14     public static Singleton3 getInstance(String name) {15         if(name == null) {16             name = Singleton3.class.getName();17             System.out.println("name == null"+"--->name="+name);18         }19         if(map.get(name) == null) {20             try {21                 map.put(name, (Singleton3) Class.forName(name).newInstance());22             } catch (InstantiationException e) {23                 e.printStackTrace();24             } catch (IllegalAccessException e) {25                 e.printStackTrace();26             } catch (ClassNotFoundException e) {27                 e.printStackTrace();28             }29         }30         return map.get(name);31     }32     //一个示意性的商业方法33     public String about() {    34         return "Hello, I am RegSingleton.";    35     }    36     public static void main(String[] args) {37         Singleton3 single3 = Singleton3.getInstance(null);38         System.out.println(single3.about());39     }40 }

时间: 2024-10-10 16:03:54

java单例模式详解[转载]的相关文章

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

单例模式的特点 一个类只允许产生一个实例化对象. 单例类构造方法私有化,不允许外部创建对象. 单例类向外提供静态方法,调用方法返回内部创建的实例化对象.  懒汉式(线程不安全) 其主要表现在单例类在外部需要创建实例化对象时再进行实例化,进而达到Lazy Loading 的效果. 通过静态方法 getSingleton() 和private 权限构造方法为创建一个实例化对象提供唯一的途径. 不足:未考虑到多线程的情况下可能会存在多个访问者同时访问,发生构造出多个对象的问题,所以在多线程下不可用这种

Java 单例模式详解

概念: java中单例模式是一种常见的设计模式,单例模式分三种:懒汉式单例.饿汉式单例.登记式单例三种. 单例模式有一下特点: 1.单例类只能有一个实例. 2.单例类必须自己自己创建自己的唯一实例. 3.单例类必须给所有其他对象提供这一实例. 单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例.在计算机系统中,线程池.缓存.日志对象.对话框.打印机.显卡的驱动程序对象常被设计成单例.这些应用都或多或少具有资源管理器的功能.每台计算机可以有若干个打印机,但只能有一个Printe

【JAVA单例模式详解】

设计模式是一种思想,适合于任何一门面向对象的语言.共有23种设计模式. 单例设计模式所解决的问题就是:保证类的对象在内存中唯一. 举例: A.B类都想要操作配置文件信息Config.java,所以在方法中都使用了Config con=new Config();但是这是两个不同的对象.对两者的操作互不影响,不符合条件. 解决思路: 1.不允许其他程序使用new创建该类对象.(别人new不可控)2.在该类中创建一个本类实例.3.对外提供一个方法让其他程序可以获取该对象. 解决方法:单例模式. 步骤:

Java 单例模式详解(转)

概念: java中单例模式是一种常见的设计模式,单例模式分三种:懒汉式单例.饿汉式单例.登记式单例三种. 单例模式有一下特点: 1.单例类只能有一个实例. 2.单例类必须自己自己创建自己的唯一实例. 3.单例类必须给所有其他对象提供这一实例. 单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例.在计算机系统中,线程池.缓存.日志对象.对话框.打印机.显卡的驱动程序对象常被设计成单例.这些应用都或多或少具有资源管理器的功能.每台计算机可以有若干个打印机,但只能有一个Printe

JAVA泛型详解2 转载

转载地址:http://www.cnblogs.com/sunwei2012/archive/2010/10/08/1845938.html 普通泛型 class Point<T>{ // 此处可以随便写标识符号,T是type的简称 private T var ; // var的类型由T指定,即:由外部指定 public T getVar(){ // 返回值的类型由外部决定 return var ; } public void setVar(T var){ // 设置的类型也由外部决定 thi

python logging模块详解[转]

一.简单将日志打印到屏幕: [python] view plaincopy import logging logging.debug('debug message') logging.info('info message') logging.warning('warning message') logging.error('error message') logging.critical('critical message') 输出: WARNING:root:warning messageER

bloom filter 详解[转]

Bloom Filter概念和原理 焦萌 2007年1月27日 Bloom Filter是一种空间效率很高的随机数据结构,它利用位数组很简洁地表示一个集合,并能判断一个元素是否属于这个集合.Bloom Filter的这种高效是有一定代价的:在判断一个元素是否属于某个集合时,有可能会把不属于这个集合的元素误认为属于这个集合(false positive).因此,Bloom Filter不适合那些“零错误”的应用场合.而在能容忍低错误率的应用场合下,Bloom Filter通过极少的错误换取了存储空

java单例模式详解

1.懒汉模式: 特点:lazy loading很明显,也就是在需要的时候才加载,也就是我们常说的延迟加载. (1)线程不安全: public class Singleton { private static Singleton instance; public static Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } } (2)线程安全: pu

Objective-C之run loop详解[转]

做了一年多的IOS开发,对IOS和Objective-C深层次的了解还十分有限,大多还停留在会用API的级别,这是件挺可悲的事情.想学好一门语言还是需要深层次的了解它,这样才能在使用的时候得心应手,出现各种怪异的问题时不至于不知所措.废话少说,进入今天的正题. 不知道大家有没有想过这个问题,一个应用开始运行以后放在那里,如果不对它进行任何操作,这个应用就像静止了一样,不会自发的有任何动作发生,但是如果我们点击界面上的一个按钮,这个时候就会有对应的按钮响应事件发生.给我们的感觉就像应用一直处于随时