### 1. 概述
> 单例模式是确保某一个类中有且只有一个实例。

----------
### 2. 饿汉式单例
``` java
public class SingletonInstance {
private static SingletonInstance mInstance = new SingletonInstance();
// 默认私有构造方法
private SingletonInstance(){}
// 静态工厂方法
public static SingletonInstance getInstance(){
return mInstance ;
}
}
```
在饿汉式单例中,静态变量会在私有构造方法中初始化,这时候唯一的实例就被创建出来了,饿汉式主要使用到的是**空间换时间**的思想,在类还在加载的时候,对象实例便已经创建好了。

----------

### 3. 懒汉式单例
```java
public class SingletonInstance {
private static SingletonInstance mInstance = null;
// 私有默认构造方法
private SingletonInstance(){}
// 静态工厂方法
public static synchronized SingletonInstance getInstance(){
if(mInstance == null){
mInstance = new SingletonInstance();
}
return mInstance;
}
}
```
对于懒汉式单例的处理,使用了``synchronized``参数修饰工厂方法,用来在多线程环境中解决同步问题,懒汉式主要是使用到的是**时间换空间**的思想,在获取实例的时候进行判断,只有在需要的时候才去创建对象,节省内存空间,但是缺点就是实现的方式是线程安全的,这样会降低访问的速度。

----------
### 4. 双重加锁单例
```java
public class SingletonInstance {
private volatile static SingletonInstance mInstance = null;
private SingletonInstance(){}
public static SingletonInstance getInstance(){
//先检查实例是否存在,如果不存在才进入下面的同步块
if(mInstance == null){
//同步块,线程安全的创建实例
synchronized (SingletonInstance .class) {
//再次检查实例是否存在,如果不存在才真正的创建实例
if(mInstance == null){
mInstance = new SingletonInstance ();
}
}
}
return mInstance;
}
}
```
双重加锁机制指的是,在每次进入``getInstance``方法先不同步,而是进入方法后,先检查实例是否存在,如果不存在才进行下面的同步块,这属于第一重检查,进入同步块过后再检查实例是否存在,如果不存在,就在同步的情况下创建一个新的实例,这属于第二重检查。这样便只需要同步一次,并减少了在多次同步情况下进行判断浪费的时间。
这种实现方式会使用到**volatile**关键字,意思是被**volatile**修饰的变量的值,不会被本地线程缓存,所有对该变量的读写都是直接操作共享内存,从而保证线程正确的处理该变量。
> **volatile**关键字在**JDK5**之前的版本中加锁失败,注意之。而且**volatile**关键字会屏蔽掉虚拟机中的一些必要的代码优化,因此虽然能实现双重检查加锁机制的单例,但并不建议大量采用。

那有什么方案可以既能达到延迟加载,又能实现线程安全的目的呢?

-----
### 5. Lazy Initialization Holder Class模式
```java
public class SingletonInstance {

private SingletonInstance(){}
/**
* 类级的内部类的实例与外部类的实例没有绑定关系,而且只有被调用到时才会装载
*/
private static class SingletonHolder{
/**
* 静态初始化,由JVM来保证线程安全
*/
private static SingletonInstance mInstance = new SingletonInstance();
}
public static SingletonInstance getInstance(){
return SingletonHolder.mInstance;
}
}
```
如果只是想简单的实现线程安全的单例,可以使用之前的**饿汉式**方式。但是缺点就是会在类装载的时候初始化对象,造成空间的浪费。
那么只要解决了类加载时自动初始化对象的问题,便可以解决问题。因此可以采用类级内部类的方式去实现,这样的话,只有在需要的时候才会创建对象实例,也达到了延迟加载和线程安全的目的。
从实现过程来看,但调用`getInstance`方法时,它会读取`SingletonHolder.mInstance`,从而初始化,在这个类被装载的时候,也会初始化静态成员,而由于静态域的特性,只会初始化一次,并且由JVM来保证线程安全。
>- 什么是类级内部类?
被`static`修饰的成员内部类才是类级内部类,如果没有被`static`修饰则被称为对象内部类,而且类级内部类与外部类对象不存在依赖关系,只有在第一次使用的时候才会被调用。
>- 多线程默认同步锁知识?
在多线程开发中,我们主要使用`synchronized`来对互斥锁进行同步控制,但是某些情况下JVM已经为我们进行了同步控制了,主要有:
1. 静态初始化方法初始化数据时;
2. 访问`final`字段时;
3. 在创建线程之前创建对象时;
4. 线程可以看见要处理的对象时;

----------
### 6. 枚举式单例
```java
public enum SingletonInstace{
// 定义一个枚举元素,它代表了一个实例
mInstance;
// 单例的操作
public void singletonOperation(){

}
}
```
使用枚举的方式既使得代码简洁,而且也由JVM来保证序列化机制,防止多次实例化,是最佳的实现单例的方式。

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

  1. java设计模式单例模式 ----懒汉式与饿汉式的区别

    常用的五种单例模式实现方式 ——主要: 1.饿汉式(线程安全,调用率高,但是,不能延迟加载.) 2.懒汉式(线程安全,调用效率不高,可以延时加载.) ——其他: 1.双重检测锁式(由于JVM底层内部模 ...

  2. Java设计模式の单例模式

    -------------------------------------------------- 目录 1.定义 2.常见的集中单例实现 a.饿汉式,线程安全 但效率比较低 b.单例模式的实现:饱 ...

  3. JAVA设计模式-单例模式(Singleton)线程安全与效率

    一,前言 单例模式详细大家都已经非常熟悉了,在文章单例模式的八种写法比较中,对单例模式的概念以及使用场景都做了很不错的说明.请在阅读本文之前,阅读一下这篇文章,因为本文就是按照这篇文章中的八种单例模式 ...

  4. Java设计模式 - - 单例模式 装饰者模式

    Java设计模式 单例模式 装饰者模式 作者 : Stanley 罗昊 [转载请注明出处和署名,谢谢!] 静态代理模式:https://www.cnblogs.com/StanleyBlogs/p/1 ...

  5. 【设计模式】Java设计模式 - 单例模式

    [设计模式]Java设计模式 - 单例模式 不断学习才是王道 继续踏上学习之路,学之分享笔记 总有一天我也能像各位大佬一样 分享学习心得,欢迎指正,大家一起学习成长! 原创作品,更多关注我CSDN: ...

  6. Java 设计模式 —— 单例模式

    1. 概念: 单例模式是一种常用的软件设计模式.核心结构中只包含一个被称为单例的特殊类.通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源.如果 ...

  7. Java设计模式 - 单例模式 (懒汉方式和饿汉方式)

    概念: Java中单例模式是一种常见的设计模式,单例模式的意思就是只有一个实例.单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例.这个类称为单例类. 单例模式的写法有好几种,这 ...

  8. java设计模式——单例模式(一)

    一. 定义与类型 定义:保证一个类仅有一个实例,并提供一个全局访问点 类型:创建型 二. 适用场景 想确保任何情况下都绝对只用一个实例 三. 优缺点 优点: 在内存里只有一个实例,减少了内存开销 可以 ...

  9. JAVA设计模式--单例模式

    单例设计模式 Singleton是一种创建型模式,指某个类采用Singleton模式,则在这个类被创建后,只可能产生一个实例供外部访问,并且提供一个全局的访问点. 核心知识点如下: (1) 将采用单例 ...

  10. Java设计模式-单例模式(Singleton)

    单例对象(Singleton)是一种常用的设计模式.在Java应用中,单例对象能保证在一个JVM中,该对象只有一个实例存在.这样的模式有几个好处: 1.某些类创建比较频繁,对于一些大型的对象,这是一笔 ...

随机推荐

  1. docker学习笔记一:基本安装和设置容器静态ip

    docker是一个lxc升级版的容器类虚拟环境,具有快速部署,灵活,易迁移的虚拟机模式,现在各大公司已经开始广泛使用为了自己方便学习linux,需要多台虚拟机环境,但是vmware开启多台虚拟机时需要 ...

  2. 【Android】Android内存机制,了解Android堆和栈

    1.dalvik的Heap和Stack 这里说的只是dalvik java部分的内存,实际上除了dalvik部分,还有native.     下面针对上面列出的数据类型进行说明,只有了解了我们申请的数 ...

  3. C语言实现单链表-04版

    前面的版本似乎没能让项目经理满意,他还希望这个链表有更多的功能: 我们接下来要解决几个比较简单的功能: Problem 1,更加友好的显示数据: 2,能够通过名字删除节点: Solution 首先我们 ...

  4. paip.mysql 批量kill 连接.

    paip.mysql 批量kill 连接. 作者Attilax  艾龙,  EMAIL:1466519819@qq.com  来源:attilax的专栏 地址:http://blog.csdn.net ...

  5. atitit. web 在线文件管理器最佳实践(1)--- elFinder 的使用流程解决之道 。打开浏览服务器文件夹java .net php

    atitit. web 在线文件管理器最佳实践(1)--- elFinder 的使用流程解决之道 .打开浏览服务器文件夹java .net php 1. 环境:::项目java web,需要打开浏览服 ...

  6. paip.提升性能3倍--使用栈跟VirtualAlloc代替堆的使用.

    paip.提升性能3倍--使用栈跟VirtualAlloc代替堆的使用. #----为什么要设计堆栈,它有什么独特的用途? 为了性能 ....  堆比栈的性能 也有的说法为了编程容易...这个是错误的 ...

  7. 优化TableView性能

    优化tableView性能(针对滑动时出现卡的现象) (2013-08-02 11:18:15) 转载▼ 标签: ios tableview it 分类: 技术文档 在iOS应用中,UITableVi ...

  8. 匿名管道读取CMD回显信息

    之前用了很坑爹的做法去读取了cmd命令的回显信息,现在发现了用匿名管道的实现方法,由于楼主没有学过Windows核心编程,找了一个代码来凑数 存下来以后研究 #include <windows. ...

  9. JQ例子:旋转木马

    使用JQ现实旋转木马超级简单,它看起来很复杂,动画好像很难实现,但其实不然. 效果图: <!DOCTYPE html> <html lang="en"> & ...

  10. Android MultiDex兼容包怎么使用?

    在Android系统中安装应用的时候,需要对Dex进行优化,但由于其处理工具DexOpt的限制,导致其id的数目不能够超过65536个.而MultiDex兼容包的出现,就很好的解决了这个问题,它可以配 ...