设计模式: 对问题行之有效的解决方式, 其实它是一种思想.

单例设计模式

解决的问题:就是可以保证一个类在内存中的对象唯一性. 即单个实例.

比如对于A 和 B 两个程序使用同一个配置信息对象时, A 对配置信息作出修改, B 也与之对应的更新配置信息, 即需要保证该对象的唯一性.

如何保证对象唯一性呢?
  1. 不允许其他程序用 new 创建该类对象
  2. 在该类中创建一个本类实例
  3. 对外提供一个方法让其他程序可以获取该对象.
步骤:
  1. 私有化该类构造函数
  2. 通过 new 在本类中创建一个本类对象
  3. 定义一个公有方法, 将创建的对象返回
两种方式
  1. 饿汉式: 类一加载, 对象就存在了.
  2. 懒汉式: 类加载进来, 没有对象, 只有调用 getInstance 方法时, 才会创建对象.

    也称为 单例设计模式的延迟加载模式. 但是, 懒汉式在多线程访问时,存在安全隐患.
  1. // 第一种方式: 饿汉式
  2. class Single
  3. {
  4. Single s = new Single(); // 在本类中创建一个本类对象
  5. private Single(){} // 私有化该类构造函数
  6. // 定义一个公有方法, 将创建的对象返回. 用于返回对象 s, 所以返回类型 Single
  7. public Single getInstance()
  8. {
  9. return s;
  10. }
  11. }
  12. class SingleDemo
  13. {
  14. public static void main(String[] args)
  15. {
  16. Single ss = Single.getInstance();
  17. }
  18. }
  19. /*
  20. 分析一: main 函数中, getInstance 方法调用不能使用对象调用, 只能使用类名调用.
  21. 所以 Single 类中该方法需要使用 static 修饰.
  22. 分析二: getInstance 方法为静态方法, 它访问的内容必须是静态的,所以对象 s 也需要静态修饰.
  23. */
  24. // 改进
  25. class Single
  26. {
  27. private static Single s = new Single();
  28. private Single(){}
  29. public static Single getInstance() // 提供该方法访问实例对象 s, 是为了对象的可控
  30. {
  31. return s;
  32. }
  33. }
  34. class SingleDemo
  35. {
  36. public static void main(String[] args)
  37. {
  38. Single ss = Single.getInstance();
  39. }
  40. }
  41. // 第二种方式: 懒汉式
  42. // 类加载进来, 没有对象, 只有调用 getInstance 方法时, 才会创建对象.
  43. class Single2
  44. {
  45. private static Single2 s = null;
  46. private Single(){}
  47. public static Single2 getInstance()
  48. {
  49. if(s==null)
  50. s = new Single2();
  51. return s;
  52. }
  53. }
  54. // 示例:下列代码的输出结果
  55. class SingleDemo
  56. {
  57. public static void main(String[] args)
  58. {
  59. Test t1 = Test.getInstance();
  60. Test t2 = Test.getInstance();
  61. t1.setNum(10);
  62. t2.setNum(20);
  63. System.out.println(t1.getNum()); // 输出 20
  64. System.out.println(t2.getNum()); // 输出 20
  65. }
  66. }
  67. class Test
  68. {
  69. private int num;
  70. private static Test t = new Test();
  71. private Test(){}
  72. public static Test getInstance()
  73. {
  74. return t;
  75. }
  76. public void setNum(int num)
  77. {
  78. this.num = num;
  79. }
  80. public int getNum()
  81. {
  82. return num;
  83. }
  84. }
  85. // 懒汉式二:避免多线程同时调用getInstance()方法, 可以使用关键字synchronized
  86. class LazySingleton {
  87. private static LazySingleton instance = null;
  88. private LazySingleton(){}
  89. public synchronized static LazySingleton getInstance() {
  90. if(instance == null){
  91. instance = new LazySingleton();
  92. }
  93. return instance;
  94. }
  95. }
  96. // 懒汉式三:为提高系统性能,对"instance = new LazySingleton()"进行锁定
  97. class LazySingleton{
  98. private static LazySingleton instance = null;
  99. private LazySingleton(){}
  100. public static LazySingleton getInstance(){
  101. if(instance == null){ // 此处,有可能造成单例对象不唯一
  102. synchronized(LazySingleton.class){
  103. instance = new LazySingleton();
  104. }
  105. }
  106. return instance;
  107. }
  108. }
  109. // 懒汉式四:双重检查锁定(Double-Check Locking)
  110. class LazySingleton{
  111. // 注意,此处增加修饰符 volatile
  112. private volatile static LazySingleton instance = null;
  113. private LazySingleton(){}
  114. public static LazySingleton getInstance(){
  115. // 第一重判断
  116. if(instance == null){
  117. // 锁定代码块
  118. synchronized(LazySingleton.class){
  119. // 第二重判断
  120. if(instance == null){
  121. instance = new LazySingleton();
  122. }
  123. }
  124. }
  125. return instance;
  126. }
  127. }
  128. //单例第三种方式: Initialization Demand Holder(IoDH)技术
  129. // 在单例类中增加一个静态(static)内部类
  130. class Singleton{
  131. private Singleton(){}
  132. // 静态类
  133. private static class HolderClass {
  134. private final static Singleton instance = new Singleton();
  135. }
  136. public static Singleton getInstance() {
  137. return HolderClass.instance;
  138. }
  139. public static void main(String args[]){
  140. Singleton s1, s2;
  141. s1 = Singleton.getInstance();
  142. s2 = Singleton.getInstance();
  143. System.out.println(s1 == s2);
  144. }
  145. }

_参考资料_
- [JavaSE 基础视频(毕向东)](https://www.bilibili.com/video/av3092292/#page=4)
- [单例模式中的双重检查](http://blog.csdn.net/chenchaofuck1/article/details/51702129)

Java 之单例设计模式的更多相关文章

  1. java的单例设计模式

    java的单例设计模式包括:饿汉设计模式和懒汉设计模式: 步骤: 1.创建一个对象把他设置为私有的成员变量,保证唯一 2.私有构造方法,防止new一个对象. 3.定义一个公开的静态方法,返回第一步创建 ...

  2. Java中如果把构造方法也私有化,如何创建对象?Java的单例设计模式——饿汉式和懒汉式区别

    Java的单例模式——饿汉式 package com.swift; //Java单例设计模式——恶汉式 public class SinglePerson { private String name= ...

  3. 【设计模式】Java之单例设计模式

    1.单例设计模式:一个类只能有一个对象 1.1 创建单例类的步骤: 1.将构造方法私有化 2.创建私有的静态成员变量 3.共有的静态成员方法,提供当前的唯一对象 1.1 创建单例的两种方式: 1.饿汉 ...

  4. java singleton(单例设计模式)

    单例设计模式的主要作用是: 1.控制资源的使用,我们对资源使用线程同步来实现并发访问. 2.节约资源,我们对一个类只进行一个实例化进行全局的资源访问,节约了内存. 3.作为通信媒介,也是数据共享,可以 ...

  5. 【Java】单例设计模式

    文章目录 单例设计模式 什么是设计模式 单例设计模式 实现 饿汉式 懒汉式 饿汉式与懒汉式的区别 饿汉式 懒汉式 单例模式的应用场景 单例设计模式 什么是设计模式 设计模式是在大量的实践中总结和理论化 ...

  6. java之单例设计模式

    什么是设计模式? 设计模式是在大量的实践中总结和理论化之后优选的代码结构.编程风格.以及解决问题的思考方式.设计模式就像是经典的棋谱,不同的棋局,我们用不同的棋谱,免去我们自己再思考和探索. 所谓单例 ...

  7. 【14】-java的单例设计模式详解

    预加载模式 代码: public class Singleton { private volatile static Singleton singleton = new Singleton(); pr ...

  8. java基础——单例设计模式(懒汉式)

    public class Test7 { // 主函数 public static void main(String[] args) { Test7.getInstance().function(9, ...

  9. Java学习笔记——单例设计模式Singleton

    单例设计模式:singleton 解决的问题: 确保程序在运行过程中,某个类的实例instance只有一份. 特点: 1 构造函数私有化 2 自己内部声明自己 3 提供一个public方法,负责实例化 ...

随机推荐

  1. Redis 5种数据类型,2种特殊数据处理策略

    5种数据类型 String [html] view plaincopy 1.String   经常使用命令:   除了get.set.incr.decr mget等操作外,Redis还提供了下面一些操 ...

  2. Atitit.增强系统稳定性----虚拟内存的设置

    Atitit.增强系统稳定性----虚拟内存的设置 1.1. 读取虚拟内存配置1 1.2. 禁止虚拟内存1 1.3. 默认所有驱动器虚拟内存1 1.4. 设置c d盘虚拟内存为系统管理1 1.5. 设 ...

  3. [css]后台管理系统布局

    知识点: 绝对定位+overflowhidden 整体思路 三大块 pg-header---需要固定 (height:48px) pg-content menu 右侧菜单-需要固定(width:200 ...

  4. C++语言基础(20)-模板的非类型参数

    一.在函数模板中使用非类型参数 #include <iostream> using namespace std; template<class T> void Swap(T & ...

  5. Go快速入门

    整理一些Go最基本的语法,旨在快速入门. 最简单的hello world package main import "fmt" func main() { fmt.Println(& ...

  6. KVC之-setValue:forKey:方法实现原理与验证

    KVC之-setValue:forKey:方法实现原理与验证 - (void)setValue:(id)value forKey:(NSString *)key方法,实现原理与验证 功能:使用一个字符 ...

  7. java全局变量使用

    1.在多线程的作用下,全局变量可能被多个程序使用,如果有人修改,全局变量就被修改了,导致别人使用的时候,出现问题 2.解决方法: 全局变量改为私有变量. 或者把全局变量改为final类型,只能读取,不 ...

  8. Centos + HHVM 生产环境安装!

    一.配置防火墙,开启80端口.3306端口 CentOS 7.0默认使用的是firewall作为防火墙,这里改为iptables防火墙. 1.关闭firewall: systemctl stop fi ...

  9. Android开发 - 图形化生成的贝塞尔插值器

    基于三次方贝塞尔曲线的插值器 在动画开发过程中,经常需要使用到插值器来满足我们的动画设计需求.然而,官方提供的插值器并不能满足所有的需求,所以我们需要自定义插值器. 下面介绍的三次方贝塞尔曲线的插值器 ...

  10. impala+hdfs+csv格式文件

    [创建目录]hdfs dfs -mkdir -p /user/hdfs/sample_data/csv/devicehdfs dfs -mkdir -p /user/hdfs/sample_data/ ...