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

设计模式(java)1——单例模式

2015-07-11 16:24 507 查看
如果要保证系统里一个类最多只能存在一个实例时,我们就需要单例模式。例如:缓存池,数据库连接池,线程池,一些应用服务实例等。

1、懒汉模式——实现懒加载但线程不安全

package singleton;

//懒汉模式(线程不安全)

public class Singleton1 {
private static Singleton1 instance;

private Singleton1() {
}

public static Singleton1 getInstance() {
if (instance == null) {
instance = new Singleton1();
}
return instance;
}
}


2、懒汉模式——实现懒加载,线程安全但效率低

public class Singleton2 {
private static Singleton2 instance;

private Singleton2() {
}

public static synchronized Singleton2 getInstance() {
if (instance == null) {
instance = new Singleton2();
}
return instance;
}
}


效率低。锁住整个方法,上述代码中的一次锁住了一个方法, 这个粒度有点大。只需锁住new 语句。

3、双重校验锁。实现懒加载,线程安全,且效率较第二种高(推荐掌握)

public class Singleton7 {
private volatile static Singleton7 singleton;

private Singleton7() {
}

public static Singleton7 getInstance() {
if (singleton == null) {
synchronized (Singleton7.class) {
if (singleton == null) {
singleton = new Singleton7();
}
}
}
return singleton;
}
}


4、饿汉模式——线程安全,但是无懒加载。

public class Singleton3 {
private static Singleton3 instance = new Singleton3();

private Singleton3() {
}

public static Singleton3 getInstance() {
return instance;
}
}


上述代码中的一个缺点是该类加载的时候就会直接new 一个静态对象出来,

当系统中这样的类较多时,会使得启动速度变慢 。现在流行的设计都是讲“延迟加载”,我们可以在第一次使用的时候才初始化第一个该类对象。所以这种适合在小系统。

5、饿汉模式(变种)——线程安全,但是无懒加载。

public class Singleton4 {
private static Singleton4 instance = null;
static {
instance = new Singleton4();
}

private Singleton4() {
}

public static Singleton4 getInstance() {
return instance;
}
}


本质上与第四中一样。

6、静态内部类——线程安全,实现懒加载。(推荐)

public class Singleton5 {
private static class SingletonHolder {
private static final Singleton5 INSTANCE = new Singleton5();
}

private Singleton5() {
}

public static final Singleton5 getInstance() {
return SingletonHolder.INSTANCE;
}
}


这种方式同样利用了classloder的机制来保证初始化instance时只有一个线程,它跟第三种和第四种方式不同的是(很细微的差别):第三种和第四种方式是只要Singleton类被装载了,那么instance就会被实例化(没有达到lazy loading效果),

而这种方式是Singleton类被装载了,instance不一定被初始化。因为SingletonHolder类没有被主动使用,只有显示通过调用getInstance方法时,才会显示装载SingletonHolder类,从而实例化instance。 想象一下,如果实例化instance很消耗资源,我想让他延迟加载,另外一方面,我不希望在Singleton类加载时就实例化,因为我不能确保Singleton类还可能在其他的地方被主动使用从而被加载,那么这个时候实例化instance显然是不合适的。这个时候,这种方式相比第三和第四种方式就显得很合理。

7、枚举——实现线程安全、懒加载、防止反序列化重新创建新的对象。本质上是最佳实现方式。

public enum Singleton6 {
INSTANCE;
public void whateverMethod() {
}
}


讨论:

单例模式与垃圾回收

当一个单例的对象长久不用时,不会被jvm的垃圾收集机制回收。

/article/1358576.html

参考博客:

/article/4029821.html

/article/1358575.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: