您的位置:首页 > 编程语言 > Java开发

java设计模式之-----单例设计模式

2015-11-26 21:39 357 查看
1.定义

单例设计模式:顾名思义,一个类只能产生一个实例,也就是说一个类只能有一个对象。就像古代的皇帝一样,只能有一个,多一个也不可以,这就是单例设计模式。

2.步骤及要点(注意)

私有化构造函数

提供一个本类的实例

提供一个对外的供外界访问的方法

实现过程

最简单的单例模式

(1)恶汉式


public class SingelInstance {

// 私有化构造函数
private SingelInstance() {

}

// 产生一个实例对象
private static SingelInstance singleInstance = new SingelInstance();

// 提供一个供外界访问的方法
public static SingelInstance getInstance() {
return singleInstance;
}
}


(2)懒汉式


public class SingelInstance1 {

private SingelInstance1() {

}

private static SingelInstance1 singelInstance1;

public static SingelInstance1 getSingelInstance1() {
//假如同步关键字
synchronized (SingelInstance1.class) {
if(singelInstance1 == null){
singelInstance1 = new SingelInstance1();
}
}
return singelInstance1;
}

}


比较: 恶汉式与懒汉式的区别仅在于先 new 与后 new 的问题,从名字就可以看出.懒汉式可以在需要的时候再new 对象,而恶汉式则是不管什么先 new 了一个对象.懒汉式的get 方法中要注意多线程的同步问题.为什么?java中new 一个对象不是简单的一个new 就能 new 出来的,只是我们自己这么觉得,其实,在编译后的执行的步奏中要经过几部才能产生出一个对象,假如不加入同步,就可能多个线程进入get 方法中产生多个对象.

注意: synchronized 关键字中不能用this关键字,为什么? 因为这个方法是静态的,静态优先于非静态,随着类的加载而加载,当对象还没产生时,静态方法就已经载入了,所以不能用this关键字,但是可以用类的class对象,原因前面已经说了.

(3)懒汉式(双重非空判断)

public class SingelInstance2 {

private SingelInstance2() {

}

private static SingelInstance2 singelInstance2;

public static SingelInstance2 getSingelInstance2() {
//双重非空判断
if (singelInstance2 == null) {

synchronized (SingelInstance1.class) {

if (singelInstance2 == null) {
singelInstance2 = new SingelInstance2();
}

}
}
return singelInstance2;
}

}


为什么这样做: 在未加入双重非空判断的实例中,多个线程每次调用的get 方法中都要对对象上锁,事实上,只有在第一次创建的时候才需要对对象上锁,之后就不要了,因为对象已经new 出来了,之后只要直接返回就可以了,所以多加入一层非空判断有利于性能的提升.

分析: 假如现在有两个线程,A, B.

A,b线程同时进入了第一个if 判断,

A首先进入同步代码块,singelInstance2 为null,紧接着new 出了一个对象.由于jvm的优化机制,jvm给SingelInstance2 分配了存储空间,并复制给了成员变量singelInstance2 .(此时还没有实例化singelInstance2 ),然后A 离开了同步代码块.

此时B进入了同步代码块,由于此时singelInstance2 不为空,紧接着B出去了,并return 了singelInstance2.

此时B打算使用singelInstance2 ,但是singelInstance2 还没有实例化成对象,于是错误发生了.

(4) 静态内部类单例模式

public class SingelInstance3 {

private SingelInstance3() {

}

private static class SingelInstanceFactory {
private static SingelInstance3 singelInstance3 = new SingelInstance3();
}

public SingelInstance3 getSingelInstance3() {
return SingelInstanceFactory.singelInstance3;
}
}


为什么这样可以:

jvm内部机制能够保证一个类被加载的时候,这个类加载的过程式互斥的,这样当我们第一次调用getSingelInstance3

的时候,jvm能够保证singelInstance3

只被创建一次,并且会保证把赋值给singelInstance3内存空间初始化完毕,这样我们就解决了刚才的问题,同时该方法也只会在第一次调用的时候使用互斥机制,同时也解决了性能上的问题.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java设计模式 java