单例模式:用来创建唯一的实例对象
想要保证对象唯一:
1.为了避免其他程序过多建立该类对象。先禁止其他程序建立该类对象
2.还为了让其他程序可以访问到该类对象,只好在本类中,自定义一个对象。
3.为了方便其他程序对自定义对象的访问,可以对外提供一些访问方式。
这三部怎么用代码体现呢?
1.将构造函数私有化。
2.在类中创建一个本类对象。
3.提供一个方法可以获取到该对象。
实现方式一:只适合单线程环境(不好)
public class Singleton { private static Singleton singleton=null; private Singleton(){ } public static Singleton getInstance(){ if(singleton==null){ singleton=new Singleton(); } return singleton; } }
缺点:只在单线程的情况下正常运行,在多线程情况下就会出问题。
例如:当两个线程同时运行到判断instance是否为空的if语句,并且instance确实没有创建好时,那么两个线程都会创建一个实例
实现方式二:多线程的情况能用。(懒汉式,不好)
public class Singleton {
private static Singleton singleton=null;
private Singleton(){
}
public static synchronized Singleton getInstance(){
if(singleton==null){
singleton=new Singleton();
}
return singleton;
}
}
在方式一的基础上加了同步锁,使得在多线程的情况下可以用,保证了在多线程的环境下也只有一个实例
实现方式三:加同步锁时,前后两次判断实例是否存在(可行)
public class Singleton {
private static Singleton singleton=null;
private Singleton(){
}
public static Singleton getInstance(){
if(singleton==null){
synchrized(Stringleton.class){
if(singleton==null){
singleton=new Singleton();
}
}
}
return singleton;
}
}
只有当singleton为null时,需要获取同步锁,创建一次实例。当实例被创建,则无需视图加锁
实现方式四:饿汉式(建议使用)
public class Singleton {
private static Singleton singleton=new Singleton();
private Singleton(){
}
public static synchronized Singleton getInstance(){
return singleton;
}
}
缺点:降低内存的使用率
实现方式五:静态内部内(建议使用)
public class Singleton {
private Singleton(){
}
private static class SingletonHolder{
private final static Singleton singleton=new Singleton();
}
public static Singleton getInstance(){
return SingletonHolder.instance;
}
}
不论是静态内部类还是非静态内部类,都是在第一次使用时才会被加载