一、单例模式简介

  单例模式是Java设计模式中常见的一种模式。主要分为懒汉式单例、饿汉式单例、登记式单例;

  单例模式的特点:  1、单例类只能有一个实例;  2、单例类必须自己创建自己的唯一的实例; 3、单例类必须给所有其他对象提供这一实例;

二、饿汉式单例 

public class SingleTonModel {

    private SingleTonModel(){}
private static final SingleTonModel singt=new SingleTonModel(); public static SingleTonModel getInstance(){
return singt;
}
}

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

三、懒汉式单例

  简单的例子:

public class SingleTonModel {

    private SingleTonModel(){}
private static SingleTonModel singt=null; public static SingleTonModel getInstance(){
if(singt==null){
singt=new SingleTonModel();
}
return singt;
}
}
Singleton通过将构造方法限定为private避免了类在外部被实例化,在同一个虚拟机范围内,Singleton的唯一实例只能通过getInstance()方法访问。

(事实上,通过Java反射机制是能够实例化构造方法为private的类的,那基本上会使所有的Java单例实现失效。此问题在此处不做讨论,姑且掩耳盗铃地认为反射机制不存在。)

但是以上懒汉式单例的实现没有考虑线程安全问题,它是线程不安全的,并发环境下很可能出现多个Singleton实例,要实现线程安全,有以下三种方式,都是对getInstance这个方法改造,保证了懒汉式单例的线程安全:(课外知识可以了解线程安全)

  改造一:在静态方法上添加关键词:synchronized,进行同步

public class SingleTonModel {

    private SingleTonModel(){}
private static SingleTonModel singt=null; public static synchronized SingleTonModel getInstance(){
if(singt==null){
singt=new SingleTonModel();
}
return singt;
}
}

  虽然通过同步保障了线程安全,但是每次都要同步,会影响性能,毕竟99%的情况下是不需要同步的。

改造二:在判断不存在实例时才进行同步

public class SingleTonModel {

    private SingleTonModel(){}
private static SingleTonModel singt=null; public static SingleTonModel getInstance(){
if(singt==null){
synchronized(SingleTonModel.class){
if(singt==null){
singt=new SingleTonModel();
}
}
}
return singt;
}
}

  在getInstance中做了两次null检查,确保了只有第一次调用单例的时候才会做同步,这样也是线程安全的,同时避免了每次都同步的性能损耗。

改造三:添加内部静态类

public class SingleTonModel {

    private SingleTonModel(){}

    private static class lanSingleton{
private static final SingleTonModel singt=new SingleTonModel();
} public static final SingleTonModel getInstance(){
return lanSingleton.singt;
}
}

利用了classloader的机制来保证初始化instance时只有一个线程,所以也是线程安全的,同时没有性能损耗,所以一般我倾向于使用这一种。

四、登记式单例(很少用)

/类似Spring里面的方法,将类名注册,下次从里面直接获取。
public class Singleton3 {
private static Map<String,Singleton3> map = new HashMap<String,Singleton3>();
static{
Singleton3 single = new Singleton3();
map.put(single.getClass().getName(), single);
}
//保护的默认构造子
protected Singleton3(){}
//静态工厂方法,返还此类惟一的实例
public static Singleton3 getInstance(String name) {
if(name == null) {
name = Singleton3.class.getName();
System.out.println("name == null"+"--->name="+name);
}
if(map.get(name) == null) {
try {
map.put(name, (Singleton3) Class.forName(name).newInstance());
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
return map.get(name);
}
//一个示意性的商业方法
public String about() {
return "Hello, I am RegSingleton.";
}
public static void main(String[] args) {
Singleton3 single3 = Singleton3.getInstance(null);
System.out.println(single3.about());
}
}

  登记式单例实际上维护了一组单例类的实例,将这些实例存放在一个Map(登记薄)中,对于已经登记过的实例,则从Map直接返回,对于没有登记的,则先登记,然后返回。

课外小知识:

  1、什么是线程安全

  如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。

  或者说:一个类或者程序所提供的接口对于线程来说是原子操作,或者多个线程之间的切换不会导致该接口的执行结果存在二义性,也就是说我们不用考虑同步的问题,那就是线程安全的。

  

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

  1. java23种设计模式之一: 单例模式(Singleton Pattern)

    单例模式(Singleton Pattern)是设计模式中比较常用的一种,下面来总结单例模式的知识,包括: 1.理解什么是单例模式.单例模式有什么优点/缺点.单例模式的应用场景: 2.再来看看Java ...

  2. java23种设计模式——四、原型模式

    源码在我的github和gitee中获取 目录 java23种设计模式-- 一.设计模式介绍 java23种设计模式-- 二.单例模式 java23种设计模式--三.工厂模式 java23种设计模式- ...

  3. java23种设计模式—— 一、设计模式介绍

    Java23种设计模式全解析 目录 java23种设计模式-- 一.设计模式介绍 java23种设计模式-- 二.单例模式 java23种设计模式--三.工厂模式 java23种设计模式--四.原型模 ...

  4. java23种设计模式——五、建造者模式

    源码在我的github和gitee中获取 目录 java23种设计模式-- 一.设计模式介绍 java23种设计模式-- 二.单例模式 java23种设计模式--三.工厂模式 java23种设计模式- ...

  5. java23种设计模式——八、组合模式

    目录 java23种设计模式-- 一.设计模式介绍 java23种设计模式-- 二.单例模式 java23种设计模式--三.工厂模式 java23种设计模式--四.原型模式 java23种设计模式-- ...

  6. java23种设计模式——七、桥接模式

    原文地址:https://www.cnblogs.com/chenssy/p/3317866.html 源码在我的github和gitee中获取 目录 java23种设计模式-- 一.设计模式介绍 j ...

  7. java23种设计模式 (转)

    文章在:http://www.cnblogs.com/maowang1991/archive/2013/04/15/3023236.html 随着自己的开发经验增加以及自己做了很多的 大专栏  jav ...

  8. java23种设计模式详解(转)

    设计模式(Design Patterns) ——可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了 ...

  9. 学习java23种设计模式自我总结

    首先先做个广告,以前看过@maowang 这位大神转的Java开发中的23种设计模式详解(转) ,但是看了之后都忘差不多了, 所以,开个帖子边学习边自我总结(纯手敲).一直以来像这种需要长久的运动,真 ...

随机推荐

  1. StringHelpers

    public class StringHelpers { public const char QUERY_STRING_DELIMITER = '&'; private static Rijn ...

  2. Joomla必备模块(转自joomla8)

    1.Akeeba Backup Core-joomla!网站备份组件. 不论是国内收费主机还是国外的收费主机甚至是免费主机,都必须考虑到数据安全问题.没有哪个主机商可以保证你的网站数据不会丢失,况且很 ...

  3. Java String的== 与 equals小结

    package hashcode; public class LearnString { public static void main(String[] args) { //1.先在栈中创建一个对S ...

  4. SQL语句的增删改查

    一.增:有2种方法 1.使用insert插入单行数据: 语法:insert [into] <表名> [列名] values <列值> 例:insert into Strdent ...

  5. Cocos2d-js 3.0 alp2 使用指南

    Download Cocos2d-JS: http://www.cocos2d-x.org/download Unzip and copy to C:/ Download JDK: http://ww ...

  6. Image控件播放 GIF文件

    uses Vcl.Imaging.GIFImg;procedure TForm1.Button2Click(Sender: TObject);begin    Image1.Picture.LoadF ...

  7. FastDFS 的部署、配置与测试的

    部署篇:http://soartju.iteye.com/blog/803477 配置篇:http://soartju.iteye.com/blog/803524 测试篇:http://soartju ...

  8. [转]flume-ng+Kafka+Storm+HDFS 实时系统搭建

    http://blog.csdn.net/weijonathan/article/details/18301321 一直以来都想接触Storm实时计算这块的东西,最近在群里看到上海一哥们罗宝写的Flu ...

  9. 深入理解Fsync----JBD内核调试 专业打杂程序员 @github yy哥

    http://hustcat.github.io/ http://www.cnblogs.com/hustcat/p/3283955.html http://blog.sina.com.cn/s/ar ...

  10. CCEditBox用法

    1.以下是CCEditBox的相关函数和类型说明: /* 编辑框的一些函数 setText("字符串"); //设置文本 setFontColor(color); //设置文本颜色 ...