单例模式的原理:保证一个类有一个实例,并且提供一个全局的访问点(内存地址唯一)
实现方式:
1、饱汉模式:
1: publicclass Singleton{
2:
3: privatestatic Singleton s = null;
4:
5: private Singleton(){
6:
7: }
8:
9: publicstatic Singleton getInstance(){
10:
11: if(s ==null){
12: s = new Singleton();
13: }
14: return s;
15: }
16: }
2、饿汉模式
1: publicclass Singleton{
2: privatestatic Singleton s = new Singleton();
3: private Sinleton(){}
4: publicstatic Singleton getInstance(){
5: return s;
6: }
7: }
单例模式的线程安全问题:
1、通过synchronized关键字来实现
1: publicclass Single
2: {
3: privatestatic Single single ;
4: private Single(){
5: }
6: publicstaticsynchronized Single getInstance(){
7: if(single == null){
8: single = new Single();
9: }
10: return single;
11: }
12: }
这样的话可以强制在程序运行过程中只有一个线程调用该方法获得该类的一个实例,但是缺点也是如此:只有在第一次使用该对象时需要同步,再次
获取该对象时就不需要再同步了,这时候的同步就变的多余了。
2、其实饿汉模式就是改善多线程的一种有效手段,这样JVM保证任何线程访问单例对象时,一定先创建该实例,代码同上
3、另外一种改善多线程的方式
1: publicclass Singleton {
2:
3: privatevolatilestatic Singleton uniqueInstance;
4:
5: private Singleton() {}
6:
7: publicstatic Singleton getInstance() {
8: if(uniqueInstance == null) { //(1)
9: //只有第一次才彻底执行这里的代码
10: synchronized() {
11: //再检查一次
12: if(uniqueInstance == null)
13: uniqueInstance = new Singleton();
14: }
15: }
16: return uniqueInstance;
17: }
18: }
在最开始如果有1、2、3个线程走到了(1)处,假设1进入了同步块,2、3等待。1实例化后,2进入同步块,发现uniqueInstance已经不为空,跳出同步块。接着3进入,又跳出同步块。
volatile关键字确保:当uniqueInstance变量被初始化成Singleton实例时,多个线程正确地uniqueInstance变量。如果性能是你关心的重点,那么这个做法可以帮你大大地减少getInstance()的时间耗费。
原创文章,作者:carmelaweatherly,如若转载,请注明出处:https://blog.ytso.com/194533.html