设计模式——单例模式
所谓类的单例设计模式,就是采用一定的方法保证在整个软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法
饿汉式(静态常量)
1.构造器私有化(防止 new)
2.类的内部创建对象
3.向外暴露一个静态公共方法,getInstance
//饿汉式(静态变量)
//写法简单,类加载时就完成了实例化
//如果从始至终未使用过这个实例,可能造成内存浪费
class Singleton{
//1.构造器私有化,外部不能new
private Singleton(){
}
//2.本类内部创建对象实例
private final static Singleton instance = new Singleton();
//3.提供一个公有的静态方法,返回对象实例
public static Singleton getInstance(){
return instance;
}
}
饿汉式(静态代码块)
//饿汉式(静态代码块)
//写法简单,类加载时就完成了实例化
//如果从始至终未使用过这个实例,可能造成内存浪费
class Singleton{
//1.构造器私有化,外部不能new
private Singleton(){
}
//2.本类内部创建对象实例
private static Singleton instance;
static{
//在静态代码块中创建单例对象
instance = new Singleton();
}
//3.提供一个公有的静态方法,返回对象实例
public static Singleton getInstance(){
return instance;
}
}
懒汉式(线程不安全)
1.起到了懒加载的效果,但是只能在单线程下使用
2.如果在多线程下,一个线程进入到if(singleton==null)语句,还未来得及向下执行,另一个线程也通过了这种判断语句,这时候便会产生多个实例,所以在多线程下不可以使用这种方式
3.在实际开发中不要使用
class Singleton{
private static Singleton instance;
private Singleton(){}
//提供一个静态的公有方法,当使用到该方法时才创建instance
//即懒汉式
public static Singleton getInstance(){
if(instance==null){
instance=new Singleton();
}
return instance;
}
}
懒汉式(线程安全)
1.解决了线程不安全问题
2.效率低,每个线程在想获得类的实例时候,执行getinstance()方法都要进行同步,而其实这个方法只执行一次实例化代码就够了,后面的想获得该类实例,直接return就可以了,方法进行同步效率低
3.在实际开发中不推荐使用
class Singleton{
private static Singleton instance;
private Singleton(){}
//提供一个静态的公有方法,当使用到该方法时才创建instance
//即懒汉式
//线程安全(加入了synchronized),解决线程安全问题
public static synchronized Singleton getInstance(){
if(instance==null){
instance=new Singleton();
}
return instance;
}
}
双重检查
1.double-check在多线程开发中经常使用,保证线程安全
2.实例化代码只用执行一次,线程安全,延迟加载,效率较高
3.推荐使用
class Singleton{
private static volatile Singleton instance;
private Singleton(){}
//提供一个静态的公有方法,加入双重检查代码,解决线程安全问题,同时解决懒加载问题
//同时保证效率,推荐使用
public static Singleton getInstance(){
if(instance==null){
synchronized (Singleton.class){
if(instance ==null){
instance = new Singleton();
}
}
}
return instance;
}
}
单例模式(静态内部类)
1.采用类装载机制来保证初始化实例时只有一个线程(JVM底层原理)
2.静态内部类方式在Singleton类被装载时并不会立刻实例化,而是在需要实例化时调用getInstance方法,才会装在对应的SingletonInstance类,从而完成Singleton的实例化
3.类的静态属性只会在第一次加载类时初始化,JVM帮我们保证了线程安全性,类初始化时其他线程无法进入
4.推荐使用
class Singleton{
private static Singleton instance;
private Singleton(){}
//写一个静态内部类,该类中有一个静态属性Singleton
private static class SingletonInstance{
private static final Singleton INSTANCE = new Singleton();
}
//提供一个静态的公有方法,直接返回SingletonInstance.INSTANCE
public static Singleton getInstance(){
return SingletonInstance.INSTANCE;
}
}
单例模式(枚举)
1.不仅能够避免多线程同步问题,而且还能防止反序列化重新创建新的对象
2.推荐使用
//使用枚举可以实现单例,推荐使用
enum Singleton{
INSTANCE;
public void sayOK(){
System.out.println("ok");
}
}
TIPS:
1.单例模式保证了系统内存中该类只存在一个对象,节省了系统资源,对于一些需要频繁创建销毁的对象,使用单例方式可以提高系统性能
2.当想实例化一个单例类时,必须要使用相应的获取对象的方法,而不是使用new