`
iluoxuan
  • 浏览: 571134 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

单例模式

 
阅读更多
今天看到群里,关于单例模式的多线程下的安全问题:

1:最简单写法的线程安全的单例,但是直接是在内存的,占空间

package com.http.concurrent.test;

public class Singleton {

    private static Singleton instance=new Singleton(); // 直接new 可以加上final 

    private Singleton() { // 私有

    }

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

 2:线程安全下 有问题的:

package com.http.concurrent.test;

public class Singleton {

    private static Singleton instance;

    private Singleton() {

    }

    public static Singleton getInstance() { // 1
        if(instance == null) { // 2
            instance=new Singleton(); // 3
        }
        return instance;
    }
}

 如果线程B,C,同时访问到了2,;A到3处,new,此时 明显B,C会再次new; 产生多个实例

 

3:简单的线程安全

public class Singleton {

    private static Singleton instance;

    private Singleton() {

    }

    public static synchronized Singleton getInstance() { // 1
        if(instance == null) { // 2
            instance=new Singleton(); // 3
        }
        return instance;
    }
}

 synchronized 锁的范围太大,效率比较低。

 

4:缩小synchronized的锁的范围,所称double-check

package com.http.concurrent.test;

public class Singleton {

    private static Singleton instance;

    private Singleton() {

    }

    public static Singleton getInstance() { // 1
        if(instance == null) { // **
            synchronized(Singleton.class) {
                if(instance == null) { // 2
                    instance=new Singleton(); // 3
                }
            }
        }
        return instance;
    }
}

 2必须有,不然并发情况下 ,可能会new 多Sinleton;

 

为了提高效率可以在上面的double-check修改下:

private volatile static Singleton instance;

加上volatile后instance变量就对 所有的线程可见了,有其他线程new一个实例,立马就能看见,**处就可以发现

 

 

/**
 * 静态内部类 单例模式
 *
 * @author ljq
 * @version 1.0
 * @since 1.0
 */
public class Singleton {

	private Singleton() {

	}

	public static final Singleton getInstance() {
		return SingletonHolder.instance;
	}

	/**
	 * 在第一次被引用时被加载
	 *  由于内部静态类只会被加载一次,故该实现方式时线程安全的
	 */
	private static class SingletonHolder {
		protected static final Singleton instance = new Singleton();
	}

	public static void main(String[] args) {
		Singleton s = Singleton.getInstance();
		Singleton s1 = Singleton.getInstance();
		System.out.println(s == s1);
	}
}

 

 并发容器实现的单例模式:

 

package xylz.study.concurrency;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

public class ConcurrentDemo1 {

    private static final ConcurrentMap<String, ConcurrentDemo1> map = new ConcurrentHashMap<String, ConcurrentDemo1>();
    private static ConcurrentDemo1 instance;
    public static ConcurrentDemo1 getInstance() {
        if (instance == null) {

            map.putIfAbsent("INSTANCE", new ConcurrentDemo1());

            instance = map.get("INSTANCE");
        }
        return instance;
    }

    private ConcurrentDemo1() {
    }

}

 当然这里只是一个操作的例子,实际上在单例模式文章中有很多的实现和比较。清单2 在存在大量单例的情况下可能有用,实际情况下很少用于单例模式。但是这个方法避免了向Map中的同一个Key提交多个结果的可能,有时候在去掉重复记录上很有用(如果记录的格式比较固定的话)。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics