java 设计模式之单例模式
来源:互联网 发布:美国大学统计 知乎 编辑:程序博客网 时间:2024/06/11 03:57
- 相信很多做java的童鞋都听说过.但是一下子让他们写出来.即便是2-3年工作经验的人,也不一定能写出来一个可用的单例模式.所以我们今天来学习学习单例模式
通常有俩种模式
立即加载-饿汉模式: 立即加载就是使用的时候对象已经实例化
public class MyObject(){
private static MyObject = new MyObject();
…………………….
}- 延时加载-懒汉模式 就是调用get()方法时,对象才被实例
单例模式:
public class SimpleSingle { /*持有 私有 静态 实例 防止被应用 * -延时加载懒汉模式 就是对象调用时 对象还没有创建 * 立即加载-饿汉模式 = new object() * * */ private static SimpleSingle instance = null; /* 私有构造方法 防止被实例化 */ private SimpleSingle() { } /** * 这里没有同步代码块.所以是线程不安全的 * @return */ public static SimpleSingle getIntance(){ if(instance == null){ instance = new SimpleSingle(); } return instance; } /**如果该对象用于序列化 可保持 序列化前后一致**/ public Object readResolve(){ return instance; } /** * 线程安全的 * 如果是将synchronized 加到方法上 就是锁了这个对象,效率低下 ,因为只需要在第一次创建的时候加锁 之后就不需要了 * */ public static synchronized SimpleSingle getInstance1(){ if(instance == null){ instance = new SimpleSingle(); } return instance; } /** * 使用同步代码块 创建 单例对象 * @return */ public static SimpleSingle getInstance3(){ if(instance == null){ synchronized (SimpleSingle.class) { if(instance == null){ instance = new SimpleSingle(); } } } return instance; }}
getIntance3() 方法看似没有什么问题
将 synchronized 关键字加在了内部,也就是说当调用的时候是不需要加
锁的,只有在 instance 为 null,并创建对象的时候才需要加锁,性能有一定的提升。但是,这样的情况,
还是有可能有问题的,看下面的情况:在 Java 指令中创建对象和赋值操作是分开进行的,也就是说
instance = new Singleton();语句是分两步执行的。但是 JVM 并不保证这两个操作的先后顺序,也就是
说有可能 JVM 会为新的 Singleton 实例分配空间,然后直接赋值给 instance 成员,然后再去初始化这
个 Singleton 实例。这样就可能出错了,我们以 A、 B 两个线程为例:
a>A、 B 线程同时进入了第一个 if 判断
b>A 首先进入 synchronized 块,由于 instance 为 null,所以它执行 instance = new Singleton();
c>由于 JVM 内部的优化机制, JVM 先画出了一些分配给 Singleton 实例的空白内存,并赋值给 instance
成员(注意此时 JVM 没有开始初始化这个实例),然后 A 离开了 synchronized 块。d>B 进入 synchronized 块,由于 instance 此时不是 null,因此它马上离开了 synchronized 块并将结果
返回给调用该方法的程序。
e>此时 B 线程打算使用 Singleton 实例,却发现它没有被初始化,于是错误发生了。
实际情况是,单例模式使用内部类来维护单例的实现, JVM 内部的机制能够保证当一个类被加载的时
候,这个类的加载过程是线程互斥的。这样当我们第一次调用 getInstance 的时候, JVM 能够帮我们保
证 instance 只被创建一次,并且会保证把赋值给 instance 的内存初始化完毕,这样我们就不用担心上
面的问题。同时该方法也只会在第一次调用的时候使用互斥机制,这样就解决了低性能问题。这样我们
暂时总结一个完美的单例模式:
public class Singleton { /* 私有构造方法,防止被实例化 */ private Singleton() { } /* 此处使用一个内部类来维护单例 */ private static class SingletonFactory { private static Singleton instance = new Singleton(); } /* 获取实例 */ public static Singleton getInstance() { return SingletonFactory.instance; } /* 如果该对象被用于序列化,可以保证对象在序列化前后保持一致 */ public Object readResolve() { return getInstance(); } }
世面上有很多很多的单例模式..但是我还是喜欢自己写的这个双重检测的单例模式 double -check -locking
使用dcl 双重检测来实现单例模式.
/** * 鉴于之前写的多线程单例模式有问题. * 这次我写一个dcl 双重检查 单例模式 * ---doble chek locking */public class MyObject { //静态实例防止被实例 private volatile static MyObject myObject; private MyObject() { } /** * 使用双检测机制来解决问题..既不需要同步代码的异步性. * 也可以保持单例. * @return */ public static MyObject getInstance(){ try { if (myObject != null) { }else{// Thread.sleep(3000); synchronized (MyObject.class) { if(myObject == null){ myObject = new MyObject(); } } } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return myObject; }}
- java设计模式之单例模式
- Java模式设计之单例模式
- Java模式设计之单例模式
- Java模式设计之单例模式
- java设计模式之单例模式
- Java模式设计之单例模式
- Java模式设计之单例模式
- Java设计模式之单例模式
- Java设计模式之单例模式
- Java设计模式之单例模式
- Java设计模式之单例模式
- Java模式设计之单例模式
- java设计模式之单例模式
- java设计模式之单例模式
- java设计模式之单例模式
- java设计模式之单例模式
- java设计模式之单例模式
- java设计模式之单例模式
- SourceTree初始设置及其使用
- 数据分析师职业规划
- Unity 烘焙贴图后再拖成预设体后场景光照信息丢失
- 程序员何去何从
- hibernate 多对多数据表配置
- java 设计模式之单例模式
- scrapy框架爬取知乎110w用户信息,并存入mysql数据库和mongoDB数据库
- wav和amr互转
- asp下sha1加密函数
- hdu1695 莫比乌斯反演
- J2EE系列之Hibernate4学习笔记(十一)--Hibernate继承关系映射(根类对应一个表)
- Redux学习
- ThinkPHP5.0-数据库
- (转)非对称加密,我终于理解了!