java单例模式的线程安全问题
2012-10-24 13:32
183 查看
传统的单例模式有两种:
第一种,优点:简单,可靠。可以保证在一个类加载器中只有一个实例。
缺点:类在被初始化的时候就会创建一个实例,不管以后会不会用到。
但是我个人认为这种缺点说的实在是有点勉强。
首先此类的实例只有在初始化的时候才会创建。网上有很多说的是在被加载的时候创建,这是严重错误的。
关于类的加载和初始化,可以参考类加载器的介绍。
这种缺点成立的情况为,此类被初始化了,但以后我们不会使用,因此白白创建了一个对象。
但是,我认为,初始化而以后不会使用的情况是几乎不太可能发生的。(但是有可能发生)
public class Singleton{
private static Singleton instance = new Singleton();
private Singleton() {
}
public static Singleton getInstance() {
return instance;
}
}
第二种,可以实现一个类加载器中只有一个实例,因为使用了同步,此方式效率极其低。
public class Singleton{
private static Singleton instance;
private Singleton() {
}
public static synchronized Singleton getInstance() {
if(instance == null)
instance = new Singleton();
return instance;
}
}
double check 方式,可以实现一个类加载器中只有一个实例,并且只有在最初没有实例的情况下才会同步,因此不会有性能上的问题。
public class Singleton {
private static Singleton instance;
private Singleton(){
}
public static Singleton getInstance(){
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
好了,那么我们现在有两个选择,第一种方式和第三种方式。
那么哪个更好一些呢?
首先,这两种方式在效率上几乎是相同的。
如果真的出现了只有初始化以后不会使用的情况(虽然这个概率很低,调用Class.forName("SomeClass“)或者用其他方式初始化,但以后再也不使用这个类的实例)
那么当然我们不愿意白白创建一个对象,选择第三种方式无疑是较好的。
如果不会出现这种情况,那么第一种方式是较好的。
如果让我选,那么我会选择第一种方式,简洁,可靠,效率比第三种方式(假设该实例没有创建,那么第一个线程在getInstance中需要获取同步锁,然后才能创建实例,并且以后再getInstance的时候都要判断instance是为空)更好。
毕竟有谁会初始化一个类,但以后不会使用它的instance呢?
第一种,优点:简单,可靠。可以保证在一个类加载器中只有一个实例。
缺点:类在被初始化的时候就会创建一个实例,不管以后会不会用到。
但是我个人认为这种缺点说的实在是有点勉强。
首先此类的实例只有在初始化的时候才会创建。网上有很多说的是在被加载的时候创建,这是严重错误的。
关于类的加载和初始化,可以参考类加载器的介绍。
这种缺点成立的情况为,此类被初始化了,但以后我们不会使用,因此白白创建了一个对象。
但是,我认为,初始化而以后不会使用的情况是几乎不太可能发生的。(但是有可能发生)
public class Singleton{
private static Singleton instance = new Singleton();
private Singleton() {
}
public static Singleton getInstance() {
return instance;
}
}
第二种,可以实现一个类加载器中只有一个实例,因为使用了同步,此方式效率极其低。
public class Singleton{
private static Singleton instance;
private Singleton() {
}
public static synchronized Singleton getInstance() {
if(instance == null)
instance = new Singleton();
return instance;
}
}
double check 方式,可以实现一个类加载器中只有一个实例,并且只有在最初没有实例的情况下才会同步,因此不会有性能上的问题。
public class Singleton {
private static Singleton instance;
private Singleton(){
}
public static Singleton getInstance(){
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
好了,那么我们现在有两个选择,第一种方式和第三种方式。
那么哪个更好一些呢?
首先,这两种方式在效率上几乎是相同的。
如果真的出现了只有初始化以后不会使用的情况(虽然这个概率很低,调用Class.forName("SomeClass“)或者用其他方式初始化,但以后再也不使用这个类的实例)
那么当然我们不愿意白白创建一个对象,选择第三种方式无疑是较好的。
如果不会出现这种情况,那么第一种方式是较好的。
如果让我选,那么我会选择第一种方式,简洁,可靠,效率比第三种方式(假设该实例没有创建,那么第一个线程在getInstance中需要获取同步锁,然后才能创建实例,并且以后再getInstance的时候都要判断instance是为空)更好。
毕竟有谁会初始化一个类,但以后不会使用它的instance呢?
相关文章推荐
- 对于java单例模式线程安全问题的思考
- 简单java单例模式 懒汉式、饿汉式以及解决线程安全问题(synchronized)
- Java单例模式的线程安全问题
- 线程安全问题
- 【转】数据存储——APP 缓存数据线程安全问题探讨
- Java静态static工具类线程安全问题研究
- struts1 action线程安全问题
- Servlet之重定向、配置访问路径、处理多个请求、生命周期、config和context、层次结构、线程安全问题
- Servlet线程安全问题。
- 【Android】自定义倒计时控件 解决复用、线程安全、列表不展示时的回调等问题
- 线程安全问题
- APP缓存数据线程安全问题
- 关于SimpleDateFormat安全的时间格式化线程安全问题
- 懒汉式单例模式的线程安全问题
- Servlet---默认Servlet/线程安全问题(网页串数据)
- Struts1和Struts2的Action线程安全问题
- 线程安全问题
- Servlet线程安全问题
- 关于struts中Action是否线程安全问题?
- 浅析Struts1和Struts2的Action线程安全问题