Java设计模式之Singleton

单例设计模式(Singleton)是最简单的设计模式。单例模式的核心就是保证全局只有一个实例并且易于访问。单例模式由于全局只会创建一个实例,所以对一些工具类使用单例模式十分适用,比如Android开发中,我们经常需要获取移动设备的高和宽,为了方便管理,我们一般选择把获取的方法封装到一个独立的工具类中,为了避免重复创建,就可以选择使用单例模式。
常用写法:
   (1)懒汉式
public class Singleton{
private static Singleton singleton = null;
	private Singleton(){
	}
	publict static Singleton getInstance(){
		if(singleton == null){
		singleton = new Singleton();
		}
		return singleton;
	}
}
 
这种方式的Singleton具有延迟加载的优点,但是缺点也是很明显的,线程不安全!比如:当两个线程并发调用Singleton.getInstance();时假如线程1恰好判断singleton为null,正要创建对象时,JVM将CPU切换给线程2,那么此时singleton仍然为null,所以线程2会创建一个Singleton对象,过了一会儿,线程1被唤醒也会再创建一个Singleton对象,此时就会有两个Singleton对象,不再满足单例的了。所以这是线程不安全的。
(2)同步锁
public class Singleton {
	private static Singleton singleton = null;
	
	private Singleton(){
	}
	public static synchronized Singleton getInstance(){
		if(singleton == null){
			singleton = new Singleton();
		}			
		return singleton;
	}
}
既然第一种线程不安全,那么我们就加个synchronized,现在线程安全了,不过因为每次调用都需判断同步锁,所以效率有点低~~~
(3)双重检验
public class Singleton {
	private static Singleton singleton = null;
	
	private Singleton(){
	}
	public static Singleton getInstance(){
		if(singleton == null){
			synchronized(Singleton.class){
				if(singleton == null){
					singleton = new Singleton();
				}
			}
		}	
		return singleton;
	}
}
这样似乎解决了效率问题,但对于singleton = new Singleton();的执行,在JVM中大致分为3步:
1.给Singleton的实例分配内存
2.初始化Singleton的构造器
3.将singleton对象指向分配的内存空间
但是在JVM编译过程中会出现指令重排的优化,所以执行顺序的不可控的,可能是1-2-3,也可能是1-3-2.这就可能导致singleton可能还没初始化,就被分配了内存空间。如果两个线程的话,可能线程1执行了1-3还没来的及执行2时,JVM就切换到了线程2,而此时singleton已经不为null了,所以线程2就会直接使用singleton,这样singleton不完整,自然而然就会报错。
(4)饿汉式
public class Singleton {
	private static Singleton singleton = new Singleton();
	
	private Singleton(){
	}
	public static Singleton getInstance(){
		return singleton;
	}
}
这个并发的问题似乎不好解决,就换个思路,不去解决。o(╯□╰)o。JLS中规定,一个类在一个ClassLoader中只会被初始化一次,这是JVM所保证的,所以就采用这种饿汉式,在类创建时就把实例给创建了,剩下的就不管了(我真TM机智)。开发中应用最多的写法。
(5)内部类式
public class Singleton {
	
	private static class SingletonHolder{
		private static Singleton INSTANCE = new Singleton();
	}
	private Singleton(){
	}
	public static Singleton getInstance(){
		return SingletonHolder.INSTANCE;
	}
}
由于SingletonHolder是内部类,所以JVM会保证线程的安全的,同时因为它是私有的,所以是基于懒汉式的。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值