Java设计模式(一)单例模式
单例模式(Singleton)是Java中最简单的设计模式之一。属于创建模式。这种模式涉及一个类,他负责创建一个对象实例,同时确保只创建一个对象实例,
这个类提供了一种方法来访问它的唯一对象,可以直接访问,而不需要实例化类的对象。 package sword2offer; class Singleton1 { /** * 一、懒汉模式 * 达到了lazy loading的效果,但是不保证线程安全,并发环境下可能会产生多个Singleton实例 */ private static Singleton1 instance ; private Singleton1() {} public static Singleton1 getInstance(){ if (instance == null) { instance = new Singleton1() ; } return instance ; } } class Singleton2 { /** * 二、懒汉模式(变种) * 达到了lazy loading的效果,线程安全,但是每次都需要同步,明显效率低下 */ private static Singleton2 instance ; private Singleton2(){} public static synchronized Singleton2 getInstance(){ if (instance == null) { instance = new Singleton2() ; } return instance ; } } class Singleton3 { /** * 三、饿汉模式 * 类在装载的时候就实例化,没有达到lazy loading的效果 ,但是线程安全。 * 基于classloder机制避免了多线程的同步问题。 */ private static Singleton3 instance = new Singleton3() ; private Singleton3() {} public Singleton3 getInstance(){ return instance ; } } class Singleton4 { /** * 四、饿汉模式(变种) * 只是加了一个静态代码块,与三相同 */ private static Singleton4 instance = null ; static { instance = new Singleton4() ; } private Singleton4() {} public static Singleton4 getInstance(){ return instance ; } } class Singleton5 { /** * 五、静态内部类 * 利用了classloder的机制来保证初始化instance时只有一个线程, * 这种方式是Singleton类被装载了,instance不一定被初始化。 * 因为SingletonHolder类没有被主动使用,只有显示通过调用getInstance方法时, * 才会显示装载SingletonHolder类,从而实例化instance。 */ private Singleton5() {} private static class T { private static Singleton5 t = new Singleton5() ; } public static Singleton5 getInstance(){ return T.t ; } } class Singleton6 { /** * 六、双重校验锁 * 考虑这样一种情况,就是有两个线程同时到达,即同时调用 getInstance() 方法,此时由于single == null ,所以很明显,
两个线程都可以通过第一重的 singleTon == null ,进入第一重 if 语句后,由于存在锁机制,所以会有一个线程进入 lock
语句并进入第二重 singleTon == null ,而另外的一个线程则会在 lock 语句的外面等待。而当第一个线程执行完
new SingleTon()语句后,便会退出锁定区域,此时,第二个线程便可以进入 lock 语句块,此时,如果没有第二重
singleTon == null 的话,那么第二个线程还是可以调用 new SingleTon()语句,这样第二个线程也会创建一个
SingleTon 实例,这样也还是违背了单例模式的初衷的。使用volatile可以禁止指令重排序。 */ private static volatile Singleton6 instance = null ; private Singleton6() {} public static Singleton6 getInstance() { if (instance == null) { synchronized(Singleton6.class){ if (instance == null) { instance = new Singleton6() ; } } } return instance ; } }
单例模式(Singleton)是Java中最简单的设计模式之一。属于创建模式。这种模式涉及一个类,他负责创建一个对象实例,同时确保只创建一个对象实例,这个类提供了一种方法来访问它的唯一对象,可以直接访问,而不需要实例化类的对象。
package sword2offer;
class Singleton1 {
/**
* 一、懒汉模式
* 达到了lazy loading的效果,但是不保证线程安全,并发环境下可能会产生多个Singleton实例
*/
private static Singleton1 instance ;
private Singleton1() {}
public static Singleton1 getInstance(){
if (instance == null) {
instance = new Singleton1() ;
}
return instance ;
}
}
class Singleton2 {
/**
* 二、懒汉模式(变种)
* 达到了lazy loading的效果,线程安全,但是每次都需要同步,明显效率低下
*/
private static Singleton2 instance ;
private Singleton2(){}
public static synchronized Singleton2 getInstance(){
if (instance == null) {
instance = new Singleton2() ;
}
return instance ;
}
}
class Singleton3 {
/**
* 三、饿汉模式
* 类在装载的时候就实例化,没有达到lazy loading的效果 ,但是线程安全。
* 基于classloder机制避免了多线程的同步问题。
*/
private static Singleton3 instance = new Singleton3() ;
private Singleton3() {}
public Singleton3 getInstance(){
return instance ;
}
}
class Singleton4 {
/**
* 四、饿汉模式(变种)
* 只是加了一个静态代码块,与三相同
*/
private static Singleton4 instance = null ;
static {
instance = new Singleton4() ;
}
private Singleton4() {}
public static Singleton4 getInstance(){
return instance ;
}
}
class Singleton5 {
/**
* 五、静态内部类
* 利用了classloder的机制来保证初始化instance时只有一个线程,
* 这种方式是Singleton类被装载了,instance不一定被初始化。
* 因为SingletonHolder类没有被主动使用,只有显示通过调用getInstance方法时,
* 才会显示装载SingletonHolder类,从而实例化instance。
*/
private Singleton5() {}
private static class T {
private static Singleton5 t = new Singleton5() ;
}
public static Singleton5 getInstance(){
return T.t ;
}
}
class Singleton6 {
/**
* 六、双重校验锁
* 考虑这样一种情况,就是有两个线程同时到达,即同时调用 getInstance() 方法,此时由于single == null ,所以很明显,两个线程都可以通过第一重的 singleTon == null ,进入第一重 if 语句后,由于存在锁机制,所以会有一个线程进入 lock 语句并进入第二重 singleTon == null ,而另外的一个线程则会在 lock 语句的外面等待。而当第一个线程执行完 new SingleTon()语句后,便会退出锁定区域,此时,第二个线程便可以进入 lock 语句块,此时,如果没有第二重 singleTon == null 的话,那么第二个线程还是可以调用 new SingleTon()语句,这样第二个线程也会创建一个 SingleTon 实例,这样也还是违背了单例模式的初衷的。
使用volatile可以禁止指令重排序。
*/
private static volatile Singleton6 instance = null ;
private Singleton6() {}
public static Singleton6 getInstance() {
if (instance == null) {
synchronized(Singleton6.class){
if (instance == null) {
instance = new Singleton6() ;
}
}
}
return instance ;
}
}