设计模式学习笔记-单例模式
2016-03-09 17:50
357 查看
一:简介
1. 在我们的一些应用中,比如缓存池,数据库连接池,线程池,一些应用服务实例等事件上我们通常需要保证在一个类中只能被创建一个对象,这这时候就需要单例模式。
2.
单例模式主要有3个特点,:
2.1
单例类确保自己只有一个实例。
2.2
单例类必须自己创建自己的实例。
2.3
单例类必须为其他对象提供唯一的实例。
3.
实现方式:懒汉单例类和饿汉单例类
3.1 懒汉式单例类
对于懒汉模式,我们可以这样理解:该单例类非常懒,只有在自身需要的时候才会行动,从来不知道及早做好准备。它在需要对象的时候,才判断是否已有对象,如果没有就立即创建一个对象,然后返回,如果已有对象就不再创建,立即返回。
懒汉模式只在外部对象第一次请求实例的时候才去创建。
3.2 饿汉式单例
对于饿汉模式,我们可以这样理解:该单例类非常饿,迫切需要吃东西,所以它在类加载的时候就立即创建对象。
3.3 懒汉模式和饿汉模式的优缺点:
懒汉模式,它的特点是运行时获得对象的速度比较慢,但加载类的时候比较快。它在整个应用的生命周期只有一部分时间在占用资源。
饿汉模式,它的特点是加载类的时候比较慢,但运行时获得对象的速度比较快。它从加载到应用结束会一直占用资源。
二:代码演示
1. 懒汉式是最简单的一种,原理就是保证该类构造方法的私有,然后通过方法返回这个唯一创造的对象,方式属于线程安全的!
public class Singleton
{
private Singleton(){
}
private static Singletoninstance = new Singleton();
private static SingletongetInstance(){
returninstance;
}
} 2. 饿汉式在开始初始化时不创建对象实体,只在需要到时创建。方式属于线程不安全的
public class Singleton
{
private Singleton(){
}
private static Singleton instance;
public static Singleton getInstance(){
if(instance == null){
return instance = new Singleton();
}else{
return instance;
}
}
}
3. 高并发状态下上一种很容易产生多个实例,所以我们需要寻找线程安全的方法,首先最容易就是添加synchronized关键字
public class ThreadSafeSingelton {
//variables and constructors…
public static synchronized ThreadSafeSingelton getInstance() {
if(instatnce ==null){
instatnce = new ThreadSafeSingelton();
}
return instatnce;
}
} <span style="color:#33cc00;">
</span> 4. 虽然添加了synchronized关键字实现了线程安全,但是在多线程高并发状态下性能却很受影响,在上一个代码片中synhchronized关键字对整体方法都加了synchronized,这是没有必要的,我们可以提取成这样,形成Doule-CheckLocking
public class DoubleCheckSingleton {
private volatile static DoubleCheckSingleton instatnce = null;
//constructors
public static DoubleCheckSingleton getInstance() {
if (instatnce == null) { //check if it is created.
synchronized (DoubleCheckSingleton.class) { //synchronize creation block
if (instatnce == null) //double check if it is created
instatnce = new DoubleCheckSingleton();
}
}
return instatnce;
}
}
5. 当然,上述已经达到目标,除此之外我们还有一种方法也可以实现同样的目标,称为Initialization on demand holder模式
public class LazyLoadedSingleton {
private LazyLoadedSingleton() {
}
private static class LazyHolder { //holds the singleton class
private static final LazyLoadedSingleton singletonInstatnce = new LazyLoadedSingleton();
}
public static LazyLoadedSingleton getInstance() {
return LazyHolder.singletonInstatnce;
}
}
6. 如果单例类实现了Serializable接口,这时我们得特别注意,因为我们知道在默认情况下,每次反序列化(Desierialization)总会创建一个新的实例对象,这样一个系统会出现多个对象供使用。解决办法可以在readResolve()方法里做文章,此方法在反序列化完成之前被执行,我们在此方法里替换掉反序列化出来的那个新的实例,让其指向内存中的那个单例对象即可
1. 在我们的一些应用中,比如缓存池,数据库连接池,线程池,一些应用服务实例等事件上我们通常需要保证在一个类中只能被创建一个对象,这这时候就需要单例模式。
2.
单例模式主要有3个特点,:
2.1
单例类确保自己只有一个实例。
2.2
单例类必须自己创建自己的实例。
2.3
单例类必须为其他对象提供唯一的实例。
3.
实现方式:懒汉单例类和饿汉单例类
3.1 懒汉式单例类
对于懒汉模式,我们可以这样理解:该单例类非常懒,只有在自身需要的时候才会行动,从来不知道及早做好准备。它在需要对象的时候,才判断是否已有对象,如果没有就立即创建一个对象,然后返回,如果已有对象就不再创建,立即返回。
懒汉模式只在外部对象第一次请求实例的时候才去创建。
3.2 饿汉式单例
对于饿汉模式,我们可以这样理解:该单例类非常饿,迫切需要吃东西,所以它在类加载的时候就立即创建对象。
3.3 懒汉模式和饿汉模式的优缺点:
懒汉模式,它的特点是运行时获得对象的速度比较慢,但加载类的时候比较快。它在整个应用的生命周期只有一部分时间在占用资源。
饿汉模式,它的特点是加载类的时候比较慢,但运行时获得对象的速度比较快。它从加载到应用结束会一直占用资源。
二:代码演示
1. 懒汉式是最简单的一种,原理就是保证该类构造方法的私有,然后通过方法返回这个唯一创造的对象,方式属于线程安全的!
public class Singleton
{
private Singleton(){
}
private static Singletoninstance = new Singleton();
private static SingletongetInstance(){
returninstance;
}
} 2. 饿汉式在开始初始化时不创建对象实体,只在需要到时创建。方式属于线程不安全的
public class Singleton
{
private Singleton(){
}
private static Singleton instance;
public static Singleton getInstance(){
if(instance == null){
return instance = new Singleton();
}else{
return instance;
}
}
}
3. 高并发状态下上一种很容易产生多个实例,所以我们需要寻找线程安全的方法,首先最容易就是添加synchronized关键字
public class ThreadSafeSingelton {
//variables and constructors…
public static synchronized ThreadSafeSingelton getInstance() {
if(instatnce ==null){
instatnce = new ThreadSafeSingelton();
}
return instatnce;
}
} <span style="color:#33cc00;">
</span> 4. 虽然添加了synchronized关键字实现了线程安全,但是在多线程高并发状态下性能却很受影响,在上一个代码片中synhchronized关键字对整体方法都加了synchronized,这是没有必要的,我们可以提取成这样,形成Doule-CheckLocking
public class DoubleCheckSingleton {
private volatile static DoubleCheckSingleton instatnce = null;
//constructors
public static DoubleCheckSingleton getInstance() {
if (instatnce == null) { //check if it is created.
synchronized (DoubleCheckSingleton.class) { //synchronize creation block
if (instatnce == null) //double check if it is created
instatnce = new DoubleCheckSingleton();
}
}
return instatnce;
}
}
5. 当然,上述已经达到目标,除此之外我们还有一种方法也可以实现同样的目标,称为Initialization on demand holder模式
public class LazyLoadedSingleton {
private LazyLoadedSingleton() {
}
private static class LazyHolder { //holds the singleton class
private static final LazyLoadedSingleton singletonInstatnce = new LazyLoadedSingleton();
}
public static LazyLoadedSingleton getInstance() {
return LazyHolder.singletonInstatnce;
}
}
6. 如果单例类实现了Serializable接口,这时我们得特别注意,因为我们知道在默认情况下,每次反序列化(Desierialization)总会创建一个新的实例对象,这样一个系统会出现多个对象供使用。解决办法可以在readResolve()方法里做文章,此方法在反序列化完成之前被执行,我们在此方法里替换掉反序列化出来的那个新的实例,让其指向内存中的那个单例对象即可
import java.io.Serializable; public class SerialibleSingleton implements Serializable { private static final long serialVersionUID = -6099617126325157499L; static SerialibleSingleton singleton = new SerialibleSingleton(); private SerialibleSingleton() { } // This method is called immediately after an object of this class is deserialized. // This method returns the singleton instance. private Object readResolve() { return singleton; } }
相关文章推荐
- mfc list control添加点击事件
- Struts2配置--Action配置
- 获取apk的包名然后重命名apk 需要appt.exe
- C++11 标准新特性: 右值引用与转移语义
- hdoj2084数塔
- xUtils===xUtils3.0基本使用规则
- tomcat基础安装篇(一)
- Leet Code OJ 260. Single Number III [Difficulty: Medium]
- JS分段上传文件(File)并使用MD5.js加密文件段用来后台校验
- setTimeout和setInterval的各自使用场景
- R programming(1)
- 关于CGRect包含交错,边缘,中心的检测
- OpenCV中的矩阵操作
- SmartClient之Data Binding
- ZOJ 3329 概率dp
- github
- JS替换函数
- 聊聊并发(三)Java线程池的分析和使用
- 算法之动态规划-->>数塔问题
- 自定闹钟改良版