文档章节

单例模式小记

小黑放大
 小黑放大
发布于 2015/01/29 11:07
字数 748
阅读 38
收藏 1

java中单例模式是一种常见的设计模式,单例模式分为三种:懒汉式单例、恶汉式单例和登记式单例。

单例模式有以下特点

 1、单例只能有一个实例

 2、单例必须自己创建自己的唯一实例

 3、单例必须给其他对象提供唯一实例

懒汉式单例

public class Singleton {
	
	private static Singleton single = new Singleton();
	
	private Singleton(){}//私有化构造器
	
	public static Singleton getInstance() {
		return single;
	}
}

 

饿汉式单例

public class Singleton {

        private static Singleton single = null;
	
        private Singleton(){}
	
	public static Singleton getInstance() {
	    if (single == null) {
	        single = new Singleton();
	    }
	    return single;
	}
}

在单线程环境下,上面的恶汉式不存在任何问题,但在多线程环境下,线程A和B,线程A第一次进入判断single为null,然后CPU切换到线程B,B判断single也为null,此时B线程会执行new Singleton(),然后CPU切回线程A,线程A继续执行也会new Singleton(),此时就会出现两个实例,问题就出来了。

考虑到多线程环境下多线程安全问题,高效的饿汉式修改如下

public class Singleton {

        private static Singleton single = null;
	
        private Singleton(){}
	
	public static Singleton getInstance() {
	    //旨在避免实例化后其它线程在进入这个方法后进入同步代码块,提高效率
	    if (single != null) {
                return single;
	    }
    	    synchronized (Singleton.class) {
	        //第一个线程进入同步代码块,多个线程等待拿同步代码块的锁,进入同步代码块
    		//当第一个线程实例化,离开同步代码块后
		//其它等待拿同步所的线程依次进入可以直接返回实例化对象
        	if (single != null) {
        	    return single;
    		}
    		single = new Singleton();
	    }
	    return single;
	}
}

如果需要进一步提高效率可以抛弃同步代码块使用Lock锁

public class Singleton {

	private static Singleton single = null;
	
	private Singleton(){}
	
	public static Singleton getInstance() {
	        //旨在避免实例化后其它线程在进入这个方法后进入同步代码块,提高效率
		if (single != null) {
		    return single;
		}
		ReentrantLock lock = new ReentrantLock(false);
		try {
		    lock.lock();
		    if (single != null) {
			return single;
		    }
		    single = new Singleton();
		} catch (Exception e) {
		    System.err.println(e.getMessage());
		} finally {
		    lock.unlock();
		}
		return single;
	}
}

 

登记式单例

等级是单例这个单例实际上维护的是一组单例类的实例(父类和子类),讲这些实例存放在一个Map(登记薄)中,对于已经登记过的实例,则从Map中获取直接返回,对于没有登记的,则先登记,再返回。

@SuppressWarnings("unchecked")
public class Singleton {

	@SuppressWarnings("rawtypes")
	private static HashMap map = new HashMap();
	
	private Singleton (){}

	static {
		Singleton single = new Singleton();
		map.put(single.getClass().getName(), single);
	}

	public static Singleton getInstance(String name) {
		if (name == null) {
			name = "Singleton";
		}
		if (map.get(name) == null) {
			try {
				map.put(name, Class.forName(name).newInstance());
			} catch (Exception e) {
				System.out.println("Error happened.");
			}
		}
		return (Singleton) map.get(name);
	}
}

其子类实现

public class SingletonChild extends Singleton {

	private SingletonChild(){}
	
	public static SingletonChild getInstance() {
		return (SingletonChild) Singleton.getInstance("SingletonChild");
	}
}

 

                                                                                                         

© 著作权归作者所有

共有 人打赏支持
小黑放大
粉丝 5
博文 20
码字总数 13257
作品 0
武汉
程序员
私信 提问
【设计模式笔记】(十六)- 代理模式

一、简述 代理模式(Proxy Pattern),为其他对象提供一个代理,并由代理对象控制原有对象的引用;也称为委托模式。 其实代理模式无论是在日常开发还是设计模式中,基本随处可见,中介者模式中...

MrTrying
2018/06/24
0
0
设计模式已经陨落了?

你现在是坐在一个程序员旁边吗?如果是的话,那么在你读下面的段落之前,有一个简单的实验。让他们到一边去,问问他们两个问题并记录下答案。首先问他们“什么是设计模式?”然后再问“说出你...

oschina
2014/03/11
9.1K
69
《PHP设计模式大全》系列分享专栏

《PHP设计模式大全》已整理成PDF文档,点击可直接下载至本地查阅 https://www.webfalse.com/read/201739.html 文章 php设计模式介绍之编程惯用法第1/3页 php设计模式介绍之值对象模式第1/5页...

kaixin_code
2018/11/06
0
0
设计模式知识梳理(1) - 结构型 - 适配器模式

一、基本概念 1.1 定义 适配器模式 将 某个类的接口 转换成 客户端期望的另一个接口 来表示,让原本因接口不能一起工作的两个类可以协同工作。 经典的适配器模式 可以分为下面三类: 类 的适...

泽毛
2018/06/24
0
0
设计模式梳理(一)

设计模式梳理(一) 总体来说设计模式分为三大类: @案例源码地址:https://gitlab.com/lxqxsyu/DisgnPattern 创建型模式 简单工厂模式 工厂类是整个模式的关键。它包含必要的判断逻辑,能够...

lxq_xsyu
2017/11/02
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Go Timer实现原理剖析

简介 快速使用 操作介绍

恋恋美食
7分钟前
0
0
记录一个奇怪的问题

环境:jdk1.8虚拟机参数:-verbose:gc -XX:+PrintGCDetails -Xmx20m -Xms20m -Xmn10m -XX:SurvivorRatio=8  -XX:+HeapDumpOnOutOfMemoryError 可以看出,eden占8M却放不下6M数据,发生了......

暗中观察
35分钟前
0
0
创建多个git账号

实习开发中我们可能一个机子上配置多个git账号,如github.com,oschina.com 或者工作账号,私人账号,这时候就2个账号用一个key,肯定会冲突,有一个会提示没权限(账号和密码对应不上) ssh ...

echojson
37分钟前
1
0
rabbitmq安装教程

RabbitMQ有Windows与Linux版本的,这里先写Windows版本的安装。 以前安装软件总是在百度上找某某安装教程,结果能按照教程安装好的软件真的不多。想起先前以为大牛说的一句话,去官网按照官网...

em_aaron
今天
7
0
Android 贝塞尔曲线实践——波浪式运动

一、波浪效果如下 贝塞尔曲线自定义波浪效果的案例很多,同样方法也很简单,大多数和本案例一样使用二次贝塞尔曲线实现,同样还有一种是PathMeasure的方式,这里我们后续补充,先来看贝塞尔曲...

IamOkay
今天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部