原地址:http://blog.csdn.net/xu__cg/article/details/70182988

Java单例模式是一种常见且较为简单的设计模式。单例模式,顾名思义一个类仅能有一个实例,并且向整个系统提供这一个实例。 
单例模式的特点:

  • 单例类仅能有一个实例。
  • 单例类必须为自己创建实例。
  • 单例类必须向外界提供获取实例的方法。 
    以下是几种实现方法

一、懒汉式单例(能够延时加载)

public class SingleTon {
private static SingleTon instance = null ;
private SingleTon(){
}
public static SingleTon getInstance(){
if(instance==null){
instance=new SingleTon();
}
return instance ;
}
}

通过是构造方法私有化使该类不能在外界实例化,只能通过public方法获取实例,从而保证实例唯一。 
但是以上的代码是线程不安全的,多线程并发的情况下,SingleTon可能产生多个实例,可以通过以下方法对getInstance方法进行改进从而保证懒汉式单例线程安全。

1.在getInstance()方法上加上同步

public class SingleTon {
private static SingleTon instance = null ;
private SingleTon(){ }
//方法同步,调用效率低!
public static synchronized SingleTon getInstance(){
if(instance==null){
instance=new SingleTon();
}
return instance ;
}
}

2.静态内部类式

public class SingleTon {
private static class SingletonClassInstance {
private static final SingleTon instance=new SingleTon();
}
private SingleTon(){
}
//方法没有同步,调用效率高!
public static SingleTon getInstance(){
return SingletonClassInstance.instance ;
}
}

3.双重校验锁式

public class SingleTon {
private volatile static SingleTon instance ; private SingleTon(){ }
public static SingleTon getInstance(){
if(instance==null){
synchronized(SingleTon.class ){
if(instance==null){
instance=new SingleTon();
}
}
}
return instance ;
}
}

二、饿汉式单例 (不能够延时加载)

public class SingleTon {
//类初始化时,立即加载这个对象,加载类时,天然的是线程安全的!
private static SingleTon instance=new SingleTon(); private SingleTon(){ }
//方法没有同步,调用效率高!
public static SingleTon getInstance(){
return instance ;
}
}

饿汉式在类创建的同时就已经创建好一个静态的对象供系统使用,以后不再改变,所以天生是线程安全的。

三、枚举式单例

public enum SingleTon {

     //这个枚举元素,本身就是单例对象!
INSTANCE; //添加自己需要的操作!
public void singletonOperation(){
} }

枚举式单例是线程安全的,调用效率高,并且可以天然的防止反射和反序列化漏洞。

四、防止反射和反序列化


事实上,通过Java反射或反序列化能够获取构造方法为private的类实例,那么所有的单例都会失效。所以为了避免这种后果,需要采取相应措施。

/**
*懒汉式单例模式(如何防止反射和反序列化漏洞)
*
*/
public class SingleTon implements Serializable {
//类初始化时,不初始化这个对象(延时加载,真正用的时候再创建)。
private static SingleTon instance ; private SingleTon(){ //私有化构造器
if(instance!=null){
throw new RuntimeException(); //防止反射
}
} //方法同步,调用效率低!
public static synchronized SingleTon getInstance(){
if(instance==null){
instance=new SingleTon();
}
return instance ;
} //反序列化时,如果定义了readResolve()则直接返回此方法指定的对象。而不需要单独再创建新对象!
private Object readResolve() throws ObjectStreamException {
return instance ;
} }

五、如何选用单例模式实现方式

  • 单例对象占用资源少,且不需要延时加载:枚举式 好于 饿汉式
  • 单例对象占用资源大,且需要延时加载:静态内部类式 好于 一般懒汉式

Java设计模式学习01——单例模式(转)的更多相关文章

  1. Java设计模式学习记录-单例模式

    前言 已经介绍和学习了两个创建型模式了,今天来学习一下另一个非常常见的创建型模式,单例模式. 单例模式也被称为单件模式(或单体模式),主要作用是控制某个类型的实例数量是一个,而且只有一个. 单例模式 ...

  2. Java设计模式学习资源汇总

    本文记录了Java设计模式学习书籍.教程资源.此分享会持续更新: 1. 设计模式书籍 在豆瓣上搜索了一把,发现设计模式贯穿了人类生活的方方面面.还是回到Java与程序设计来吧. 打算先归类,再浏览,从 ...

  3. Java设计模式之《单例模式》及应用场景

    摘要: 原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/6510196.html 所谓单例,指的就是单实例,有且仅有一个类实例,这个单例不应该 ...

  4. Java设计模式学习记录-模板方法模式

    前言 模板方法模式,定义一个操作中算法的骨架,而将一些步骤延迟到子类中.使得子类可以不改变一个算法的结构即可重新定义该算法的某些特定步骤. 模板方法模式 概念介绍 模板方法模式,其实是很好理解的,具体 ...

  5. Java设计模式学习记录-状态模式

    前言 状态模式是一种行为模式,用于解决系统中复杂的对象状态转换以及各个状态下的封装等问题.状态模式是将一个对象的状态从该对象中分离出来,封装到专门的状态类中,使得对象的状态可以灵活多变.这样在客户端使 ...

  6. Java设计模式学习记录-观察者模式

    前言 观察者模式也是对象行为模式的一种,又叫做发表-订阅(Publish/Subscribe)模式.模型-视图(Model/View)模式. 咱们目前用的最多的就是各种MQ(Message Queue ...

  7. Java设计模式学习记录-备忘录模式

    前言 这次要介绍的是备忘录模式,也是行为模式的一种 .现在人们的智能手机上都会有备忘录这样一个功能,大家也都会用,就是为了记住某件事情,防止以后自己忘记了.那么备忘录模式又是什么样子的呢?是不是和手机 ...

  8. Java设计模式学习记录-迭代器模式

    前言 这次要介绍的是迭代器模式,也是一种行为模式.我现在觉得写博客有点应付了,前阵子一天一篇,感觉这样其实有点没理解透彻就写下来了,而且写完后自己也没有多看几遍,上次在面试的时候被问到java中的I/ ...

  9. Java设计模式学习记录-解释器模式

    前言 这次介绍另一个行为模式,解释器模式,都说解释器模式用的少,其实只是我们在日常的开发中用的少,但是一些开源框架中还是能见到它的影子,例如:spring的spEL表达式在解析时就用到了解释器模式,以 ...

随机推荐

  1. 20179223《Linux内核原理与分析》第四周学习笔记

    补交第三周作业 完成一个简单的时间片轮转多道程序内核 1.使用实验楼的虚拟机打开shell,用cd LinuxKernel/linux-3.9.4进入linux-3.9.4. 2.执行命令qemu - ...

  2. webdriver元素定位

    #1 通过id定位 driver.find_element_by_id("pop_setting_save").click() #2 通过name定位 driver.find_el ...

  3. SmartSql 动态仓储

    动态代理仓储 SmartSql源码:https://github.com/Ahoo-Wang/SmartSql 简介 动态代理仓储(SmartSql.DyRepository)组件是SmartSql非 ...

  4. hbase单机及集群安装配置,整合到hadoop

    问题导读:1.配置的是谁的目录conf/hbase-site.xml,如何配置hbase.rootdir2.如何启动hbase?3.如何进入hbase shell?4.ssh如何达到互通?5.不安装N ...

  5. Hadoop1.x安装配置文件及参数说明

    一.常用文件及参数说明Core-site.xml       配置Common组件的属性 hdfs-site.xml         配置hdfs参数,比如备份数目,镜像存放路径 Mapred-sit ...

  6. JavaScript 定时任务多事件冲突问题

    var iCount = setInterval(ChangeTime, 3500);//3.5秒请求一次函数 function ChangeTime() { $.ajax({ type: " ...

  7. Java通过aws java sdk在AWS S3上进行操作客户端

    有两种方式可以安装aws java sdk:方式一:可以在这个网站上下载适用于 Java 的 AWS 开发工具包https://aws.amazon.com/cn/sdk-for-java/点击网页右 ...

  8. 从wiresharp看tcp三次握手

    我们知道,传输层是OSI模型中用户进行数据传输的分层,目前仅有TCP和UDP两种协议可用.TCP为了进行传输控制,引入了三次握手机制,以确保通信连接的建立.道理很简单,我们跟别人打电话聊天时,对方拿起 ...

  9. Linux下使用locale命令设置语言环境

    locale命令设置语言环境 在Linux中通过locale来设置程序运行的不同语言环境,locale由 ANSI C提供支持.locale的命名规则为_.,如zh_CN.GBK,zh代表中文, CN ...

  10. windows下编译nginx+nginx_rtmp_modue(vs2013)

    阅读官方编译windows版本的方法 http://nginx.org/en/docs/howto_build_on_win32.html 我的环境 Windows 7 Ultimate 64,Vis ...