设计模式是一种思想,适合于任何一门面向对象的语言。共有23种设计模式。

单例设计模式所解决的问题就是:保证类的对象在内存中唯一。

举例:

A、B类都想要操作配置文件信息Config.java,所以在方法中都使用了Config con=new Config();但是这是两个不同的对象。对两者的操作互不影响,不符合条件。

解决思路:

1.不允许其他程序使用new创建该类对象。(别人new不可控)
2.在该类中创建一个本类实例。
3.对外提供一个方法让其他程序可以获取该对象。

解决方法:单例模式。

步骤:
1.私有化该类的构造函数
2.通过new在本类中创建一个本类对象。
3.定义一个共有的方法将创建的对象返回。

一、饿汉式

雏形:

  1. class Single
  2. {
  3. private static final Single s=new Single();
  4. private Single(){}
  5. public static Single getInstance()
  6. {
  7. return s;
  8. }
  9. }

为什么方法是静态的:不能new对象却想调用类中方法,方法必然是静态的,静态方法只能调用静态成员,所以对象也是静态的。

为什么对象的访问修饰符是private,不能是public 吗?不能,如果访问修饰符是Public,则Single.s也可以得到该类对象,这样就造成了不可控。

举例:

  1. public class Single
  2. {
  3. private String name;
  4. public String getName() {
  5. return name;
  6. }
  7. public void setName(String name) {
  8. this.name = name;
  9. }
  10. private static final Single s=new Single();
  11. private Single(){}
  12. public static Single getInstance()
  13. {
  14. return s;
  15. }
  16. }
  1. public class Main {
  2. public static void main(String args[])
  3. {
  4. Single s=Single.getInstance();
  5. s.setName("张三");
  6. System.out.println(s.getName());
  7. }
  8. }

最后结果为:张三

 二、懒汉式

前面的是饿汉式单例模式,下面开始讲解懒汉式单例模式。

  1. class Single
  2. {
  3. private static Single s=null;
  4. private Single(){}
  5. public static Single getInstance()
  6. {
  7. if(s==null)
  8. s=new Single();
  9. return s;
  10. }
  11. }

我们可以看到懒汉式和饿汉式相比的区别就是懒汉式创建了延迟对象同时饿汉式的实例对象是被修饰为final类型。

懒汉式的好处是显而易见的,它尽最大可能节省了内存空间。

但是懒汉式又有着弊端,在多线程编程中,使用懒汉式可能会造成类的对象在内存中不唯一,虽然通过修改代码可以改正这些问题,但是效率却又降低了。而且如果想要使用该类对象,就必须创建对象,所以虽然貌似使用懒汉式有好处,但是在实际开发中使用的并不多。

总结:

懒汉式在面试的时候经常会被提到,因为知识点比较多,而且还可以和多线程结合起来综合考量。

饿汉式在实际开发中使用的比较多。

三、懒汉式在多线程中的安全隐患以及解决方案、优化策略。

下面分析懒汉式在多线程中的应用和出现的问题以及解决方法。

懒汉式在多线程中出现的问题:

懒汉式由于多加了一次判断

  1. if(s==null)

导致了线程安全性隐患。因为CPU很有可能在执行完if语句之后切向其它线程。解决线程安全性问题的关键就是加上同步锁。

1.使用同步函数

我们可以直接使用同步函数:

  1. class Single
  2. {
  3. private static Single s=null;
  4. private Single()
  5. {
  6. }
  7. public static synchronized Single getInstance()
  8. {
  9. if(s==null)
  10. s=new Single();
  11. return s;
  12. }
  13. }

但是直接使用同步函数的方法效率十分低下,因为每次调用此方法都需要先判断锁。

2.使用同步代码块

我们也可以使用同步代码块:

  1. class Single
  2. {
  3. private static Single s=null;
  4. private Single()
  5. { }
  6. public static Single getInstance()
  7. {
  8. synchronized(Single.class)
  9. {
  10. if(s==null)
  11. s=new Single();
  12. return s;
  13. }
  14. }
  15. }

但是每次调用getInstance方法仍然会判断锁,事实上没有改变效率问题。

3.最终解决方案

我们可以使用另外一种方式,达到只判断一次锁,并且实现同步的目的:

  1. class Single
  2. {
  3. private static Single s=null;
  4. private Single()
  5. { }
  6. public static Single getInstance()
  7. {
  8. if(s==null)//和上面的相比只是多增加了一次判断
  9. {
  10. synchronized(Single.class)
  11. {
  12. if(s==null)
  13. s=new Single();
  14. return s;
  15. }
  16. }
  17. return s;
  18. }
  19. }

观察代码可以发现和上面的代码相比,只是增加了一次判断而已,但是,这一次判断却解决了效率问题。

我们可以分析一下这个代码:

4.最终解决方案代码分析和总结

假设我们现在并没有创建单例对象,即s==null,那么我们调用getInstance方法的时候,会进入if块,然后进入同步代码块,此时,别的线程如果想要创建Single实例,就必须获取锁;等当前线程创建完实例对象,释放锁之后,假设正巧有几个线程已经进入了if块中,它们会拿到锁,进入同步代码块,但是由于进行了判空操作,所以不会创建Single实例,而是直接返回已经创建好的Single实例。如果有多个其他线程进入了if块,当它们依次进入同步代码块的时候,同理也不会创建新的Single实例。而没有进入if块的线程,判空操作之后不满足条件,进不了if块,而直接执行了下一条语句return s;其后的线程调用getInstance方法时,只会判断一次s==null,不满足条件直接返回Single单例s,这样就大大提高了了执行效率。

总结:在代码

  1. if(s==null)
  2. {
  3. synchronized(Single.class)
  4. {
  5. if(s==null)
  6. s=new Single();
  7. return s;
  8. }
  9. }
  10. return s;
  1. 中,第一行代码是第一次判空操作,目的是提高效率;第三行代码是同步代码块的入口,目的是保证线程安全;第五行代码进行第二次判空操作是为了保证单例对象的唯一性

【JAVA单例模式详解】的更多相关文章

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

    单例模式的特点 一个类只允许产生一个实例化对象. 单例类构造方法私有化,不允许外部创建对象. 单例类向外提供静态方法,调用方法返回内部创建的实例化对象.  懒汉式(线程不安全) 其主要表现在单例类在外 ...

  2. Java 单例模式详解

    概念: java中单例模式是一种常见的设计模式,单例模式分三种:懒汉式单例.饿汉式单例.登记式单例三种. 单例模式有一下特点: 1.单例类只能有一个实例. 2.单例类必须自己自己创建自己的唯一实例. ...

  3. Java 单例模式详解(转)

    概念: java中单例模式是一种常见的设计模式,单例模式分三种:懒汉式单例.饿汉式单例.登记式单例三种. 单例模式有一下特点: 1.单例类只能有一个实例. 2.单例类必须自己自己创建自己的唯一实例. ...

  4. 9种Java单例模式详解

    单例模式的特点 一个类只允许产生一个实例化对象. 单例类构造方法私有化,不允许外部创建对象. 单例类向外提供静态方法,调用方法返回内部创建的实例化对象. 懒汉式(线程不安全) 其主要表现在单例类在外部 ...

  5. java单例模式详解

    饿汉法 饿汉法就是在第一次引用该类的时候就创建对象实例,而不管实际是否需要创建.代码如下: public class Singleton { private static Singleton = ne ...

  6. android java 设计模式详解 Demo

    android java 设计模式详解 最近看了一篇设计模式的文章,深得体会,在此基础我将每种设计模式的案例都写成Demo的形式,方便读者研究学习, 首先先将文章分享给大家: 设计模式(Design ...

  7. Java内部类详解

    Java内部类详解 说起内部类这个词,想必很多人都不陌生,但是又会觉得不熟悉.原因是平时编写代码时可能用到的场景不多,用得最多的是在有事件监听的情况下,并且即使用到也很少去总结内部类的用法.今天我们就 ...

  8. 黑马----JAVA迭代器详解

    JAVA迭代器详解 1.Interable.Iterator和ListIterator 1)迭代器生成接口Interable,用于生成一个具体迭代器 public interface Iterable ...

  9. C++调用JAVA方法详解

    C++调用JAVA方法详解          博客分类: 本文主要参考http://tech.ccidnet.com/art/1081/20050413/237901_1.html 上的文章. C++ ...

随机推荐

  1. BZOJ 2654: tree

    Description \(n\) 个点, \(m\) 条边,边有权值和黑/白色,求含有 \(need\) 个白边的生成树. Sol 二分+Kruskal. 将每条白边都加上一个权值,然后跑最小生成树 ...

  2. mysql+mybatis+存储过程+事务 + 多并发流水号获取

    数据库存储过程 drop PROCEDURE generate_serial_number; CREATE PROCEDURE generate_serial_number( ), IN param_ ...

  3. htpasswd命令

    htpasswd命令是Apache的Web服务器内置工具,用于创建和更新储存用户名.域和用户基本认证的密码文件. 语法 htpasswd(选项)(参数) 选项 -c:创建一个加密文件:-n:不更新加密 ...

  4. mac os x安装php7.0和phalcon3.0

    1,安装xampp(with php7.0) 下载地址: https://www.apachefriends.org/download.html 2,安装phalcon3.0 cd ~/git clo ...

  5. 用Kibana和logstash快速搭建实时日志查询、收集与分析系统

    Logstash是一个完全开源的工具,他可以对你的日志进行收集.分析,并将其存储供以后使用(如,搜索),您可以使用它.说到搜索,logstash带有一个web界面,搜索和展示所有日志. kibana ...

  6. ACM/ICPC 之 BFS(离线)+康拓展开(TSH OJ-玩具(Toy))

    祝大家新年快乐,相信在新的一年里一定有我们自己的梦! 这是一个简化的魔板问题,只需输出步骤即可. 玩具(Toy) 描述 ZC神最擅长逻辑推理,一日,他给大家讲述起自己儿时的数字玩具. 该玩具酷似魔方, ...

  7. 【转】Android Support v4、v7、v13的区别和应用场景

    google提供了Android Support Library package 系列的包来保证来高版本sdk开发的向下兼容性,即我们用4.x开发时,在1.6等版本上,可以使用高版本的有些特性,如fr ...

  8. [转] This Android SDK requires Android Developer Toolkit version 23.0.0 or above

    问题描述: This Android SDK requires Android Developer Toolkit version 23.0.0 or above.  Current version ...

  9. HTML中表格元素TABLE,TR,TD及属性的语法

    table:表格元素及属性 <table width="80%" border="1" cellspacing="1" cellpad ...

  10. 【leetcode】Repeated DNA Sequences(middle)★

    All DNA is composed of a series of nucleotides abbreviated as A, C, G, and T, for example: "ACG ...