应用场景
- 频繁访问数据库或文件的对象。
- 工具类对象;
- 创建对象时耗时过多或耗费资源过多,但又经常用到的对象;
- 频繁访问数据库或文件的对象。
- 工具类对象;
- 创建对象时耗时过多或耗费资源过多,但又经常用到的对象;
优点
- 内存中只存在一个对象,节省了系统资源。
- 避免对资源的多重占用,例如一个文件操作,由于只有一个实例存在内存中,避免对同一资源文件的同时操作。
- 内存中只存在一个对象,节省了系统资源。
- 避免对资源的多重占用,例如一个文件操作,由于只有一个实例存在内存中,避免对同一资源文件的同时操作。
缺点
- 获取对象时不能用new
- 单例对象如果持有Context,那么很容易引发内存泄露。
- 单例模式一般没有接口,扩展很困难,若要扩展,只能修改代码来实现。
- 获取对象时不能用new
- 单例对象如果持有Context,那么很容易引发内存泄露。
- 单例模式一般没有接口,扩展很困难,若要扩展,只能修改代码来实现。
Single Thread
=========================================================
public class Singleton{
private static Singleton instance;
private Singleton(){};
public static Singleton getInstance(){
if(instance==null)
instance=new Singleton();
return instatnce;
}
}
=========================================================
Multi Thread
第一次判断是为了避免不必要的同步,第二次判断是确保在此之前没有其他线程进入到sychronized块创建了新实例
=========================================================
public class Singleton{
private static Singleton instance;
private Singleton(){};
public static Singleton getInstance(){
if(instance==null){
sychronized(Singleton.class){
if(instance==null)
instance=new Singleton();
}
}
return instatnce;
}
}
=========================================================
这段代码看上去非常完美,但是,,,却有隐患!问题出现在哪呢?主要是在instance=new Singleton();这段代码上。这段代码会编译成多条指令,大致上做了3件事:
(1)给Singleton实例分配内存
(2)调用Singleton()构造函数,初始化成员字段
(3)将instance对象指向分配的内存(此时instance就不是null啦~)
上面的(2)和(3)的顺序无法得到保证的,也就是说,JVM可能先初始化实例字段再把instance指向具体的内存实例,也可能先把instance指向内存实例再对实例进行初始化成员字段。其实一般情况下这两种方式肯定不会影响到程序的正确执行,但是会影响到上面的单例模式代码。在第二次判断instance是否为null时,可能已经在内存中进行实例化了,就差第(3)步了,可是我们的判断依然为true,导致这个线程在次new一个Singleton对象。
=========================================================
public class Singleton{
private volatile static Singleton instance;
private Singleton(){};
public static Singleton getInstance(){
if(instance==null){
sychronized(Singleton.class){
if(instance==null)
instance=new Singleton();
}
}
return instatnce;
}
}
=========================================================
相比前面的代码,这里只是对instance变量加了一个volatile关键字volatile关键字的作用是:线程每次使用到被volatile关键字修饰的变量时,都会去堆里拿最新的数据。换句话说,就是每次使用instance时,保证了instance是最新的。
No comments:
Post a Comment