1. 认识单例模式
1. 定义:一个类中仅有一个实例,并提供一个访问它的全局访问点。
2. 结构:仅一个Singleton类,其中包含一个static类变量,而类变量的类型就是Singleton类,而且Singleton类的构造方法必须声明为private,通过一个static修饰的getInstance方法使外界来访问这个类的唯一实例。
3. 参考代码实现:有两种实现方式,一种是懒惰式(延迟加载),一种是饥饿式,懒惰式是以时间换取空间,而饥饿式是以空间换取时间
//饥饿式实现,以空间换时间,即在加载Singleton 类时就已经创建该类的单例对象
public class Singleton {
//通过static来声明一个Singleton实例对象为类变量,只会创建一次
private static Singleton s=new Singleton();
//禁止通过构造方法生成Singleton的实例对象
private Singleton(){
}
public static Singleton getIntance(){
return s;
}
//Singleton类中的其他方法操作
public void SingletonOperation(){
System.out.println("Singleton中的操作方法");
}
//Singleton类中可以有实例变量
private int data;
}
//懒惰式单例模式,直到第一次调用getIntance()方法时才生成Singleton2的单例对象
public class Singleton2 {
//通过static来声明一个Singleton实例对象为类变量,只会创建一次
private static Singleton2 s=null;
//禁止通过构造方法生成Singleton的实例对象
private Singleton2(){
}
public static Singleton2 getIntance(){
if(s==null){
s=new Singleton2();
}
return s;
}
//Singleton类中的其他方法操作
public void SingletonOperation(){
System.out.println("Singleton中的操作方法");
}
//Singleton类中可以有实例变量
private int data;
}
2. 理解单例模式
1. 功能:保证单例类在运行期间只会被创建一个实例,并为该实例提供一个对外访问的方法。
2. 范围:单例模式只会在同一个ClassLoader以及其子ClassLoader范围内有效。
3. 多线程并发情况下的问题:在上面的参考代码中,懒惰式单例模式的实现如果是处于多线程并发情况下调用getInstance方法,就有可能会发生创建多个Singleton实例,也就是说会出现线程不安全现象,原因在于 s=new Singleton2() 该行代码处。所以为了保证线程安全,可以使用synchronized关键字来保证线程安全,但性能可能会不太好,推荐另一种实现方式
//懒惰式单例模式的保证线程安全的实现
public class Singleton3 {
//通过该静态内部类,就可以实现延迟加载
/*
* 由于该类是静态内部类,Singleton3Holder与Singleton3类并无依赖关系
* 也就是说,加载Singleton3类时不会自动加载Singleton3Holder,
* 只有调用Singleton3Holder内部的方法或变量时才会加载该类,而且加载只会加载一次,
* 所以这就相当于通过jvm的类加载机制来实现了延迟加载并保证了并发安全
*/
private static class Singleton3Holder{
private static Singleton3 s=new Singleton3();
}
// 禁止通过构造方法生成Singleton的实例对象
private Singleton3() {
}
public static Singleton3 getIntance() {
return Singleton3Holder.s;
}
// Singleton类中的其他方法操作
public void SingletonOperation() {
System.out.println("Singleton中的操作方法");
}
// Singleton类中可以有实例变量
private int data;
}