HeadFirst 设计模式 5 单例模式(巧克力工厂)
2015-08-13 16:52
441 查看
单例模式:
确保一个类只有一个实例,并提供一个全局访问点。
将类设计成自己管理的一个单独的实例,同时也避免其他类再自行产生实例。想要取得单例实例,通过单例类是唯一的途径。
提供实例的全局访问点:当需要实例时,向类查询,他会返回单个实例。
注意:多线程会破坏上述经典的单例实现。
处理多线程
(1)将getInstance()变成同步(synchronized)方法(简单直接但是性能低,对性能无要求可用此方法)
public class Singleton{
private static Singleton uniqueInstance;
//其他有用实例化变量
private Singleton(){}
/*通过增加synchronized关键字到getInstance()方法中,
我们迫使每个线程在进入这个方法之前,要先等候别的线程离开该方法。
也就是说,不会有两个线程可以同时进入这个方法*/
public static synchronized Singleton getInstance(){
if(uniqueInstance==null){
uniqueInstance=new Singleton();
}
return uniqueInstance;
}
//其他方法
}(2)提前创建实例,而不用延迟实例化的做法(可行)
public class Singleton{
//在静态初始化器中(static initialize)中创建单件。这段代码保证了线程安全。
private static Singleton uniqueInstance=new Singleton();
//其他有用实例化变量
private Singleton(){}
public static Singleton getInstance(){
return uniqueInstance; //已有实例,直接使用
}
//其他方法
}
(3)用“双重检查加锁”,在getInstance()中减少使用同步(关注性能可用此法)
利用双重检查加锁(double-checked locking),首先检查是否实例已经创建了,如果未创建,“才”进行同步。如此,只有第一次才会同步。
public class Singleton{
//volatile关键字确保:当uniqueInstance变量被初始化成Singleton实例时,多个线程正确的处理uniqueInstance变量
private volatile static Singleton uniqueInstance;
//其他有用实例化变量
private Singleton(){}
public static Singleton getInstance(){
//检查实例,如果不存在,就进入同步区域。只有第一次才彻底执行这些代码。
if(uniqueInstance==null){
synchronized (Singleton.class){
//再次检查,如果仍是null才创建实例
if(uniqueInstance==null){
uniqueInstance=new Singleton();
}
}
return uniqueInstance;
}
//其他方法
}
要点:
(1)单例模式确保程序中一个类最多只有一个实例
(2)单例模式提供全局访问点
(3)在Java中实现单例模式需要私有的构造器、一个静态方法和一个静态变量
(4)考虑性能和资源的限制,选择合适的方案实现单例,以解决多线程的问题(必须认定所有的程序都是多线程的)
(5)若使用多个类加载器可能会导致单例失效而产生多个实例
(6)如果使用JVM1.2或之前的版本,必须建立单例注册表,以免垃圾收集器将单例回收
(7)在1.4以及更早的Java版本中许多JVM对volatile关键字的实现会导致双重检查加锁的失效
确保一个类只有一个实例,并提供一个全局访问点。
将类设计成自己管理的一个单独的实例,同时也避免其他类再自行产生实例。想要取得单例实例,通过单例类是唯一的途径。
提供实例的全局访问点:当需要实例时,向类查询,他会返回单个实例。
public class Singleton{ private static Singleton uniqueInstance; //其他有用实例化变量 private Singleton(){} public static Singleton getInstance(){ if(uniqueInstance==null){ uniqueInstance=new Singleton(); } return uniqueInstance; } //其他方法 }
注意:多线程会破坏上述经典的单例实现。
处理多线程
(1)将getInstance()变成同步(synchronized)方法(简单直接但是性能低,对性能无要求可用此方法)
public class Singleton{
private static Singleton uniqueInstance;
//其他有用实例化变量
private Singleton(){}
/*通过增加synchronized关键字到getInstance()方法中,
我们迫使每个线程在进入这个方法之前,要先等候别的线程离开该方法。
也就是说,不会有两个线程可以同时进入这个方法*/
public static synchronized Singleton getInstance(){
if(uniqueInstance==null){
uniqueInstance=new Singleton();
}
return uniqueInstance;
}
//其他方法
}(2)提前创建实例,而不用延迟实例化的做法(可行)
public class Singleton{
//在静态初始化器中(static initialize)中创建单件。这段代码保证了线程安全。
private static Singleton uniqueInstance=new Singleton();
//其他有用实例化变量
private Singleton(){}
public static Singleton getInstance(){
return uniqueInstance; //已有实例,直接使用
}
//其他方法
}
(3)用“双重检查加锁”,在getInstance()中减少使用同步(关注性能可用此法)
利用双重检查加锁(double-checked locking),首先检查是否实例已经创建了,如果未创建,“才”进行同步。如此,只有第一次才会同步。
public class Singleton{
//volatile关键字确保:当uniqueInstance变量被初始化成Singleton实例时,多个线程正确的处理uniqueInstance变量
private volatile static Singleton uniqueInstance;
//其他有用实例化变量
private Singleton(){}
public static Singleton getInstance(){
//检查实例,如果不存在,就进入同步区域。只有第一次才彻底执行这些代码。
if(uniqueInstance==null){
synchronized (Singleton.class){
//再次检查,如果仍是null才创建实例
if(uniqueInstance==null){
uniqueInstance=new Singleton();
}
}
return uniqueInstance;
}
//其他方法
}
要点:
(1)单例模式确保程序中一个类最多只有一个实例
(2)单例模式提供全局访问点
(3)在Java中实现单例模式需要私有的构造器、一个静态方法和一个静态变量
(4)考虑性能和资源的限制,选择合适的方案实现单例,以解决多线程的问题(必须认定所有的程序都是多线程的)
(5)若使用多个类加载器可能会导致单例失效而产生多个实例
(6)如果使用JVM1.2或之前的版本,必须建立单例注册表,以免垃圾收集器将单例回收
(7)在1.4以及更早的Java版本中许多JVM对volatile关键字的实现会导致双重检查加锁的失效
相关文章推荐
- 华三交换机mstp生成树配置
- 8-13 部分小功能总结
- 【并查集】【NOI 2015】【bzoj 4195】程序自动分析
- MYSQL中取当前年份的第一天和当前周,月,季度的第一天/最后一天
- Heavily reliance on forensic tools is risky
- 动态规划——C编辑最短距离
- nginx-1.8.0反向代理服务器的搭建与配置
- nginx-1.8.0反向代理服务器的搭建与配置
- 博弈汇集
- 整理的正则表达式笔记
- 数据结构
- 数据仓库备份思路
- Scala学习笔记(二):运行脚本文件
- 第五章 编码/加密——《跟我学Shiro》
- 基于TCP/IP协议的网络编程
- hdu-2553 N皇后问题
- hdu 4630 No Pain No Game【线段树 离线操作】
- HDU-1698 Just a Hook(区间更新)
- Tab Bar Controller 的二级页面
- 剑指offer第41题 和为s的两个数