目录html
之前对设计模式没有太大感受。如今慢慢在工做中愈来愈感受设计模式的重要性,因此决定重头来好好学习整理下经常使用的设计模式。
本文介绍的最初级的一个设计模式 单例模式java
java中单例模式定义:一个类有且仅有一个实例,而且自行实例化向整个系统提供。设计模式
应用: 一个系统中多线程对一个文件进行操做,这个文件就须要保证只有一个实例,等等安全
说明:饿汉式意思就是不管系统需不须要使用该类的实例对象,先在类加载的时候建立好
优势:实现简单
缺点:容易形成内存的浪费多线程
该方式是在该类被加载的时候,就建立好了实例化对象。不容许其余地方经过构造方法来建立对象,只能经过提供的指定公共方法来获取惟一的对象。jvm
public class SingletonDemo1 { //static 确保在类加载的时候就会初始化该对象 private final static SingletonDemo1 singleton = new SingletonDemo1(); // 必须是私有构造方法,防止其余地方经过构造方法来实例化对象 private SingletonDemo1(){ } // 是一个公共的静态方法,用于对外提供惟一的对象 public static SingletonDemo1 getInstance(){ return singleton; } }
根据枚举的特性,可使用枚举来实现单例模式学习
public class SingletonDemo3 { // 不容许其余地方经过构造方法进行实例化对象 private SingletonDemo3(){} //对外提供可获取惟一实例化对象的公共方法 public static SingletonDemo3 getInstance(){ return Singleton.SINGLETON.getInstance(); } private enum Singleton{ SINGLETON; private SingletonDemo3 singleton; Singleton(){ singleton = new SingletonDemo3(); } public SingletonDemo3 getInstance(){ return singleton; } } }
说明:懒汉式意思就是在系统第一次须要使用该类的实例对象时,再建立该类的实例对象。
优势:不形成内存不必的浪费
缺点:实现相对较难.net
在有多线程使用的状况下不要使用,不然可能会形成建立多个实例对象。通常建议不使用该种方式。线程
public class SingletonDemo1 { //static 确保在类加载的时候就会初始化该对象 private static SingletonDemo1 singleton = null; // 必须是私有构造方法,防止其余地方经过构造方法来实例化对象 private SingletonDemo1(){ } // 是一个公共的静态方法,用于对外提供惟一的对象 public static SingletonDemo1 getInstance(){ if(singleton==null){ singleton = new SingletonDemo1(); } return singleton; } }
因为上面的方式,是在执行getInstance()方法时,多线程使用时可能出现建立多个对象的状况。那能够直接将该方法进行同步,保证任意时间,最可能是能一个线程使用该方法。设计
public class SingletonDemo2 { //static 确保在类加载的时候就会初始化该对象 private static SingletonDemo2 singleton = null; // 必须是私有构造方法,防止其余地方经过构造方法来实例化对象 private SingletonDemo2(){ } // 是一个公共的静态方法,用于对外提供惟一的对象 public static synchronized SingletonDemo2 getInstance(){ if(singleton==null){ singleton = new SingletonDemo2(); } return singleton; } }
缺点:过重了,每一个线程在每次使用的时候,都须要进行同步,而实际上只是在第一次获取该类的实例对象时须要同步,日后使用不须要同步。
该方式只会在未实例化对象时,才同步进行实例化对象。实例化后就不须要再进行同步了。
public class SingletonDemo2 { //static 确保在类加载的时候就会初始化该对象 private static volatile SingletonDemo2 singleton = null; // 必须是私有构造方法,防止其余地方经过构造方法来实例化对象 private SingletonDemo2(){ } // 是一个公共的静态方法,用于对外提供惟一的对象 public static SingletonDemo2 getInstance(){ if(singleton==null){ synchronized (SingletonDemo2.class){ if(singleton==null) { //为了防止多个线程进行实例化 singleton = new SingletonDemo2(); } } } return singleton; } }
有么有注意到,使用了volatitle关键字,为何要使用volatile关键字?
答:这里使用了volatile一个重要的特性——禁止JVM指令重排序
singleton = new SingletonDemo2()的在jvm内存中会有三步,1)分配内存;2)初始化对象;3)将对象指向分配的内存。jvm在会在不改变最终执行结果的状况下对指令进行重排序,即:可能执行顺序是1->3->2,如果在执行执行3还未执行2时,其余线程执行使用,则会报错。
(参考:http://www.javashuo.com/article/p-plwggyio-cp.html)
http://www.javashuo.com/article/p-qjktkfot-ck.html
http://www.runoob.com/design-pattern/singleton-pattern.html
java实例化对象过程说明:http://www.javashuo.com/article/p-rtbvcfpv-ey.html