简介
单例模式在是指在程序运行过程中只存在一个该类的实例,这对于复杂的项目来说减轻了项目运行时的负担。因此在许多框架中有着重要的应用,比如Spring.
对于严格限制的单例模式,单例类应该具有以下特点:
1.私有化构造器
2.在类的内部将实例创建
3.提供静态公共的获取实例的方法
单例模式分为饿汉式(一种)和懒汉式(三种),下面将依次介绍:
饿汉式
饿汉式,即在类加载时就将其初始化 或者置于静态块中
/**
* 饿汉式单例1
*/
public class SingletonStudent {
// 在类加载时就将其初始化 或者置于静态块中
private static SingletonStudent singleStudent =new SingletonStudent();
// 私有化构造器
private SingletonStudent(){};
public static SingletonStudent getInstance()
{
return SingletonStudent.singleStudent;
}
}
优点:实现了单例模式,不用考虑线程安全的问题
缺点:增加了程序启动时的负担。
懒汉式第一种
懒汉式,即在程序调用时再将对应变量初始化
/**
* 懒汉式单例第一种
*/
public class LazySingletonStudent1 {
private static LazySingletonStudent1 student1 =null;
private LazySingletonStudent1(){};
/**
* 优点:锁住这个方法,使得同时只有一个线程进入了方法,并且只有在调用到时才会被初始化,
* 缺点:虽然保证了单例,但是在单例被实例化后,仍然同时只有一个线程进入了方法,对性能影响严重
*/
public static synchronized LazySingletonStudent1 getInstance()
{
if(student1==null){
student1=new LazySingletonStudent1();
}
return student1;
}
}
懒汉式第二种
/**
* 懒汉式单例第二种
*/
public class LazySingletonStudent2 {
private static LazySingletonStudent2 student2 =null;
private LazySingletonStudent2(){};
/**
* 优点:满足懒加载需求,采用同步块的形式,使得加载完成的后续使用中对性能无影响
* 缺点:初次使用为多线程访问同时加载时有影响。
*/
public static LazySingletonStudent2 getInstance()
{
if(student2==null){
synchronized (student2) {
if(student2==null){
student2=new LazySingletonStudent2();
}
}
}
return student2;
}
}
懒汉式第三种
/**
* 懒汉式单例第三种
*/
public class LazySingletonStudent3 {
private LazySingletonStudent3(){};
/**
* 优点:利用内部类的延迟加载机制,
* 在内部类加载时对自身变量进行初始化,完美解决了前两种方法的缺陷
*/
private static class InnerSingleStu{
private static final LazySingletonStudent3 innerStu = new LazySingletonStudent3();
}
public static LazySingletonStudent3 getInstance()
{
return InnerSingleStu.innerStu;
}
}
一笔题外话:SpringContainer容器中的bean是单例的,由Spring创建,在调用时传递引用。而这些单例对象在多线程下能保持线程安全的原因是,这些对象的属性都是无状态的,(没有实参和集合,只有形参,而且,形参也是无状态的),具体请参考《java并发编程实战》