原文地址:http://blog.csdn.net/jason0539/article/details/23297037

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

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

  1. public class Singleton {
  2. private static Singleton uniqueInstance = null;
  3. private Singleton() {
  4. // Exists only to defeat instantiation.
  5. }
  6. public static Singleton getInstance() {
  7. if (uniqueInstance == null) {
  8. uniqueInstance = new Singleton();
  9. }
  10. return uniqueInstance;
  11. }
  12. // Other methods...
  13. }

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

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

  1. package jason.single;
  2. public class TestStream {
  3. String name = null;
  4. public String getName() {
  5. return name;
  6. }
  7. public void setName(String name) {
  8. this.name = name;
  9. }
  10. private TestStream() {
  11. }
  12. private static TestStream ts1 = null;
  13. public static TestStream getTest() {
  14. if (ts1 == null) {
  15. ts1 = new TestStream();
  16. }
  17. return ts1;
  18. }
  19. public void printInfo() {
  20. System.out.println("the name is " + name);
  21. }
  22. }
  1. package jason.single;
  2. public class TMain {
  3. public static void main(String[] args){
  4. TestStream ts1 = TestStream.getTest();
  5. ts1.setName("jason");
  6. TestStream ts2 = TestStream.getTest();
  7. ts2.setName("0539");
  8. ts1.printInfo();
  9. ts2.printInfo();
  10. if(ts1 == ts2){
  11. System.out.println("创建的是同一个实例");
  12. }else{
  13. System.out.println("创建的不是同一个实例");
  14. }
  15. }
  16. }

运行结果:

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

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. }
  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. }

《JAVA与模式》之单例模式(转载)的更多相关文章

  1. Java 序列化 序列化与单例模式 [ 转载 ]

    Java 序列化 序列化与单例模式 [ 转载 ] @author Hollis 本文将通过实例+阅读Java源码的方式介绍序列化是如何破坏单例模式的,以及如何避免序列化对单例的破坏. 单例模式,是设计 ...

  2. Java ------ 工厂模式、单例模式

    工厂模式 简单工厂模式: 1.创建Car接口 public interface Car { public void drive(); } 2.创建两个实体类,分别实现Car接口 public clas ...

  3. 《JAVA与模式》之单例模式

    在阎宏博士的<JAVA与模式>一书中开头是这样描述单例模式的: 作为对象的创建模式,单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例.这个类称为单例类. 单例模式的 ...

  4. Java中的GOF23(23中设计模式)--------- 单例模式(Singleton)

    Java中的GOF23(23中设计模式)--------- 单例模式(Singleton) 在Java这这门语言里面,它的优点在于它本身的可移植性上面,而要做到可移植的话,本身就需要一个中介作为翻译工 ...

  5. 《JAVA与模式》之单例模式 [转]

    在阎宏博士的<JAVA与模式>一书中开头是这样描述单例模式的: 作为对象的创建模式,单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例.这个类称为单例类. 单例模式的 ...

  6. Java设计模式(4)——创建型模式之单例模式(Singleton)

    一.概述 弥补一下之前没有给设计模式下的定义,先介绍一下设计模式(引用自百度百科): 设计模式(Design Pattern)是一套被反复使用.多数人知晓的.经过分类的.代码设计经验的总结. 使用设计 ...

  7. 《JAVA与模式》之观察者模式(转载)

    <JAVA与模式>之观察者模式(转载)  原文链接:http://www.cnblogs.com/java-my-life/archive/2012/05/16/2502279.html ...

  8. 资源池模式和单例模式实现的自定义数据库连接池java实现版

    在企业级开发中,我们往往不会直接使用原生的JDBC操作来实现与数据库得连接.因为数据库的连接是一个很宝贵的资源且耗时,我们往往会在内存中引入一个资源池来统一管理数据库的连接.这个模式也被总结为一种设计 ...

  9. java future模式 所线程实现异步调用(转载

    java future模式 所线程实现异步调用(转载) 在多线程交互的中2,经常有一个线程需要得到另个一线程的计算结果,我们常用的是Future异步模式来加以解决.Future顾名思意,有点像期货市场 ...

  10. 《JAVA与模式》之责任链模式 【转载】

    转载自java_my_life的博客 原文地址:http://www.cnblogs.com/java-my-life/archive/2012/05/28/2516865.html 在阎宏博士的&l ...

随机推荐

  1. javascript捕获事件event

    var e = e ? e : window.event; window.event ? window.event.cancelBubble = true : e.stopPropagation(); ...

  2. springboot项目中报错:listener does not currently know of SID given in connect descriptor

    springboot项目中报错:listener does not currently know of SID given in connect descriptor 出现这个问题的原因是SID写错了 ...

  3. Spring4.2 集成ActiveMQ5.14

    1:libs 2:web.xml <?xml version="1.0" encoding="UTF-8"?> <web-app versio ...

  4. 微信小程序尝鲜一个月现状分析

    概述 曾记得在微信小程序还没有上线的时候,大家都是翘首以待.希望在张小龙,在企鹅的带领下,走出差别于原生开发的还有一条移动开发的道路,我也是一直关注着.知道1月9号,微信小程序最终对外开放了,作为第一 ...

  5. Keepalived系列一:安装Keepalived

    1:简介 它是一个基于VRRP协议来实现的WEB服务高可用方案,可以利用其来避免单点故障.一个WEB服务至少会有2台服务器运行Keepalived,一台为主服务器(MASTER),一台为备份服务器(B ...

  6. BFC特性 形成BFC

    1.示例代码 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <ti ...

  7. 元素高度、宽度获取 style currentStyle getComputedStyle getBoundingClientRect

    1.示例代码 (1)html <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> ...

  8. eclipse mavenWeb项目真正实现热部署(修改java代码和页面文件不用重启tomcat)

            1.前言 首先,本文创作灵感源于博客园园作者signheart,特此鸣谢!原文链接见文末推荐: 百度都搜破了,全网讲的都是如何将maven项目部署到tomcat上,对于热部署的认知,真 ...

  9. SICK LMS111激光雷达的使用

    LMS111系列是SICK推出的一款用于室外区域防撞.测量及安防的激光扫描器.LMS111同西克其他扫描器一样,采用成熟的ToF原理,非接触式检测,且加入了最新的多次回波检测技术(两次回波),使得LM ...

  10. Dubbo架构设计详解(转收藏)

    转自:http://shiyanjun.cn/archives/325.html Dubbo是Alibaba开源的分布式服务框架,它最大的特点是按照分层的方式来架构,使用这种方式可以使各个层之间解耦合 ...