Java设计模式之Singleton
2016-03-24 16:07
706 查看
单例设计模式(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会保证线程的安全的,同时因为它是私有的,所以是基于懒汉式的。
相关文章推荐
- 学习使用Eclipse中的Ant的小实例
- SpringMvc+Mybatis整合hbase时出现的问题
- 基于java平台的常用资源整理
- eclipse设置jvm
- 基于java平台的常用资源整理
- SpringMVC+Shiro权限管理
- java调用.net的webservice[转]
- java web QQ(四)
- Struts2国际化
- SpringMVC工作原理
- Spring 整合 Hibernate 时启用二级缓存
- Springmvc+ajax如何通过ajax封装多个对象参数,controller接受多个对象参数
- Java基础之泛型
- Java单例模式
- Java 后台sql注入
- eclipse+hadoop 配置过程中遇到的问题
- String 的hashCode源码实现原理
- Java [Leetcode 318]Maximum Product of Word Lengths
- 又一波 有关 java 静态代码块 代码块 构造函数执行顺序问题
- Java第四次作业