单例模式
2016-05-05 12:12
246 查看
在Java设计模式中,单例模式无疑是使用特别频繁的一种,本文就介绍一下单利模式的常用形式
单例模式主要分为饿汉式和懒汉式,作用是保证这个类只会被实例化一个对象。饿汉式是在穿件对象引用的时候就实例化对象,懒汉式用于延迟加载,将会在需要使用此对象时实例化对象,懒汉式往往会带来一些安全性问题。下面就详细描述一下两种单利模式。
饿汉式单例模式(例):
饿汉式比较简单,就不再赘述,重点看注释
懒汉式将从不安全到安全由浅入深讲解,先看最简单的写法:
现在我们考虑另外一个问题,假如现在有连个线程,线程A和线程B,当线程A执行完判断,并且判断结果为空,但是还没有执行singleInstance = new SingleInstance()语句时,线程B获得了CPU资源,线程B也做了判断,由于线程A没有实例化对象,所以线程B继续执行,实例化了一个singleInstance对象,此时就有了一个singleIntance对象,然后线程A有获得了CPU资源,继续执行,由于线程A在之前已经执行过if语句,所以此时不在执行,依然认为singleInstance为空,所以也继续执行,实例化了一个singleInstance对象,此时就有了两个singleIntance对象,也不能满足只能实例化一个对象的需求,所以需要再次修改。
现在我们来加上同步锁就可以解决这个问题了
这样就解决线程安全问题了,但是新的问题产生了,每次调用getSingleInstance()方法是都需要去判断同步锁,这样太浪费资源,所以仍然需要改进,我们给他加上双重判断,如果是空就执行同步锁判断,否则就不去执行了
到此就完美解决了线程安全的问题,这是一种懒汉式的写法,另外一种是使用内部类来实现,先看代码
可以看到我们在SingleInstance中添加了一个私有静态内部类InnerClass,在InnerClass中实例化了一个对象。然后在SingleInstance提供的共有方法中来返回了这个对象
单例模式主要分为饿汉式和懒汉式,作用是保证这个类只会被实例化一个对象。饿汉式是在穿件对象引用的时候就实例化对象,懒汉式用于延迟加载,将会在需要使用此对象时实例化对象,懒汉式往往会带来一些安全性问题。下面就详细描述一下两种单利模式。
饿汉式单例模式(例):
public class SingleInstance{ //创建并实例化一个私有的静态对象,private保证不会被外界直接调用,static保证只会被创建一个对象 private static SingleInstance singleInstance = new SingleInstance(); //私有化构造器,作用是不让外界使用构造方法来实例化对象,而是只能通过SingleInstance提供的共有方法来获取 private SingletonInstance(){ } //提供一个公有方法,外界通过此方法获取到这个类的对象 public static SingletonInstance getInstance(){ return singleInstance; } }
饿汉式比较简单,就不再赘述,重点看注释
懒汉式将从不安全到安全由浅入深讲解,先看最简单的写法:
public class SingleInstance{ private SingleInstance(){} private static SingleInstance singleInstance; public SingleInstnce getSingleIntance(){ singleInstance = new SingleInstance(); return singleInstance; } }从代码中可以看到,外界如果调用了getInstance()方法就会去实例化一个singleInstance方法,这样不能满足只允许实例化一个对象的需求,所以我们加上一个判断,如果singleInstance对象为null就实例化,否则就直接返回,如以下代码
public class SingleInstance{ private SingleInstance(){} private static SingleInstance singleInstance; public SingleInstnce getSingleIntance(){ if(singleInstance == null){ singleInstance = new SingleInstance(); } return singleInstance; } }
现在我们考虑另外一个问题,假如现在有连个线程,线程A和线程B,当线程A执行完判断,并且判断结果为空,但是还没有执行singleInstance = new SingleInstance()语句时,线程B获得了CPU资源,线程B也做了判断,由于线程A没有实例化对象,所以线程B继续执行,实例化了一个singleInstance对象,此时就有了一个singleIntance对象,然后线程A有获得了CPU资源,继续执行,由于线程A在之前已经执行过if语句,所以此时不在执行,依然认为singleInstance为空,所以也继续执行,实例化了一个singleInstance对象,此时就有了两个singleIntance对象,也不能满足只能实例化一个对象的需求,所以需要再次修改。
现在我们来加上同步锁就可以解决这个问题了
public class SingleInstance{ private SingleInstance(){} private static SingleInstance singleInstance; public SingleInstnce getSingleIntance(){ synchonized(SingleInstance.class){ if(singleInstance == null){ singleInstance = new SingleInstance(); } } return singleInstance; } }
这样就解决线程安全问题了,但是新的问题产生了,每次调用getSingleInstance()方法是都需要去判断同步锁,这样太浪费资源,所以仍然需要改进,我们给他加上双重判断,如果是空就执行同步锁判断,否则就不去执行了
public class SingleInstance{ private SingleInstance(){} private static SingleInstance singleInstance; public SingleInstnce getSingleIntance(){ if(singleInstance == null){ synchonized(SingleInstance.class){ if(singleInstance == null){ singleInstance = new SingleInstance(); } } } return singleInstance; } }
到此就完美解决了线程安全的问题,这是一种懒汉式的写法,另外一种是使用内部类来实现,先看代码
public class SingleInstance{ private SingleInstance(){} private static class InnerClass { private static SingleInstance singleInstance = new SingleInstance(); } public SingleInstance getSingleInstance(){ return SingleInstance.InnerClass.singleInstance; } }
可以看到我们在SingleInstance中添加了一个私有静态内部类InnerClass,在InnerClass中实例化了一个对象。然后在SingleInstance提供的共有方法中来返回了这个对象
相关文章推荐
- 研发模式演变(转载)
- Codeforces 119C DP
- LeetCode 016 3Sum Closest
- 汇总内表数据:at end of方法和collect方法
- x264 参数详解【很强大、很细致,不再为不懂啥意思很烦恼】
- shell从入门到放弃(上)
- x264参数 中文说明
- int,String,数组的默认值输出问题
- linux基础之bash特性
- Linux内核设计与实现 第十七章
- 添加搜索路径到FileUtils
- HDU 1317 XYZZY
- GridView添加网格线
- Android Studio开发环境变量配置
- android广播的使用方式
- x264编码指南——码率控制
- 请教一个问题:关于 webrtc 通信的问题
- 《Linux内核设计与实现》第17章读书笔记
- Django session 详解-part II-session
- js代码的调试