Java中的单例模式
来源:互联网 发布:注册域名后怎么建站 编辑:程序博客网 时间:2024/06/07 23:29
转载出处:
http://www.blogjava.net/kenzhh/archive/2013/03/15/357824.html
http://www.cnblogs.com/hupp/p/4487521.html
第一种(懒汉,线程不安全,只适合单线程环境):
package test;public class Singleton { private static Singleton instance=null; private Singleton(){ } public static Singleton getInstance(){ if(instance==null){ instance=new Singleton(); } return instance; }}注解:
Singleton的静态属性instance中,只有instance为null的时候才创建一个实例,构造函数私有,确保每次都只创建一个,避免重复创建。
缺点:只在单线程的情况下正常运行,在多线程的情况下,就会出问题。例如:当两个线程同时运行到判断instance是否为空的if语句,并且instance确实没有创建好时,那么两个线程都会创建一个实例。
第二种(懒汉,线程安全):
public class Singleton { private static Singleton instance=null; private Singleton(){ } public static synchronized Singleton getInstance(){ if(instance==null){ instance=new Singleton(); } return instance; }}注解:
在第一种的基础上加上了同步锁,使得在多线程的情况下可以用。例如:当两个线程同时想创建实例,由于在一个时刻只有一个线程能得到同步锁,当第一个线程加上锁以后,第二个线程只能等待。第一个线程发现实例没有创建,创建之。第一个线程释放同步锁,第二个线程才可以加上同步锁,执行下面的代码。由于第一个线程已经创建了实例,所以第二个线程不需要创建实例。保证在多线程的环境下也只有一个实例。
缺点:每次通过getInstance方法得到singleton实例的时候都有一个试图去获取同步锁的过程。而众所周知,加锁是很耗时的,效率很低,能避免则避免。
第三种(饿汉,建议使用):
public class Singleton { private static Singleton instance=new Singleton(); private Singleton(){ } public static Singleton getInstance(){ return instance; }}
注解:
初试化静态的instance创建一次。如果我们在Singleton类里面写一个静态的方法不需要创建实例,它仍然会早早的创建一次实例。而降低内存的使用率。
缺点:没有lazy loading的效果,从而降低内存的使用率。
第四种(静态内部类,建议使用):public class Singleton { private Singleton(){ } private static class SingletonHolder{ private final static Singleton instance=new Singleton(); } public static Singleton getInstance(){ return SingletonHolder.instance; }}注解:
定义一个私有的内部类,在第一次用这个嵌套类时,会创建一个实例。而类型为SingletonHolder的类,只有在Singleton.getInstance()中调用,由于私有的属性,他人无法使用SingleHolder,不调用Singleton.getInstance()就不会创建实例。
优点:达到了lazy loading的效果,即按需创建实例。
第五种(双重校验锁):
public class Singleton { private volatile static Singleton instance=null; private Singleton(){ } public static Singleton getInstance(){ if(instance==null){ synchronized(Singleton.class){ if(instance==null){ instance=new Singleton(); } } } return instance; }}注解:只有当instance为null时,需要获取同步锁,创建一次实例。当实例被创建,则无需试图加锁。
缺点:用双重if判断,复杂,容易出错。
第六种(枚举):
public enum Singleton { INSTANCE; public void whateverMethod() { } }这种方式是Effective Java作者Josh Bloch 提倡的方式,它不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象,可谓是很坚强的壁垒啊,不过,个人认为由于1.5中才加入enum特性,用这种方式写不免让人感觉生疏,在实际工作中,我也很少看见有人这么写过。
总结
有两个问题需要注意:
1、如果单例由不同的类装载器装入,那便有可能存在多个单例类的实例。假定不是远端存取,例如一些servlet容器对每个servlet使用完全不同的类 装载器,这样的话如果有两个servlet访问一个单例类,它们就都会有各自的实例。
2、如果Singleton实现了java.io.Serializable接口,那么这个类的实例就可能被序列化和复原。不管怎样,如果你序列化一个单例类的对象,接下来复原多个那个对象,那你就会有多个单例类的实例。
我们系统在Web容器启动的时候,加载初始化Servlet的时候,会实例化一下对象,这样在后面使用的时候可以判断当前实例是否为空,不为空,返回实例。
- java中的单例模式
- java中的单例模式
- java中的单例模式
- java中的单例模式
- Java中的单例模式
- java中的单例模式
- java中的单例模式
- Java中的单例模式
- JAVA中的单例模式
- Java中的单例模式
- java中的单例模式
- JAVA中的单例模式
- Java中的单例模式
- Java中的单例模式
- java中的单例模式
- java中的单例模式
- Java中的单例模式
- java中的单例模式
- PyQt5系列教程(十一)发送信号时传参
- Swing组件及三大布局管理器
- POJ 1700
- Android 之 BroadcastReceiver (二) 常见的几个系统广播
- [Unity Shader] Fixed Function Shader
- Java中的单例模式
- 组合数 【DFS】(保存路径)
- Java 集合系列之 Set架构 TreeSet HashSet 详细介绍(源码解析)和使用示例
- UndefinedMetricWarning: Precision is ill-defined and being set to 0.0 due to no predicted samples.
- 一个脑补的基于现有家居电器自动开关的插座(通过GPRS模块与手机通信)
- [Audacity][编译][步骤三]Audacity 相关源码下载
- Mongo 安装和启动
- nginx事件模块执行过程
- WebView的使用小结