单例模式
确保一个类中只有一个实例,自行实例化并向整个系统提供这个实例,这个类被称为单例类,它提供全局的访问方法
特点
在类中只有一个实例,并提供一个静态的getInstacne()方法用于外界唯一访问这个实例
防止在外部对其实例化,构造函数私有化
在单例类内部定义了一个Singleton类型的静态对象,作为外部共享的唯一实例
举例
windows操作系统中的任务管理器,回收站等,在系统中都只有一个实例,是典型的的单例模式
五种实现方式
饿汉式(线程安全)
顾名思义,既然是恶汉,肯定是饥不择食啦,所以不管三七二十一,在类加载的时候就把实例给创建出来咯
//饿汉式
public class SingletonDemo2 {
private static SingletonDemo2 instance = new SingletonDemo2();
//私有化构造器
private SingletonDemo2(){
}
public static SingletonDemo2 getInstance(){
return instance;
}
}
优点:不用考虑线程同步问题
缺点:如果getInstance方法,则会造成资源浪费
懒汉式(线程安全,延时加载)
创建实例这么麻烦的事情。。当然要拖到最后一刻啦,等需要用到实例的时候再创建
//懒汉式
public class SingletonDemo1 {
private static SingletonDemo1 instance;
//私有化构造器
private SingletonDemo1(){
}
public static synchronized SingletonDemo1 getInstance(){
if(instance == null){
instance = new SingletonDemo1();
}
return instance;
}
}
优点:延迟加载,资源利用率提高
缺点:同步造成并发效率低
双重加锁机制
在之前的懒汉式中,它的缺点非常明显,为了保证在多线程的工作下能正常工作,它进行了同步,下一个线程想要获取对象,就必须等待上一个线程释放锁之后,才可以继续运行。但是百分之99.9的情况下都是不需要同步的,所以它的效率是非常低的,于是我们进行优化,避免整个方法被锁,只对需要锁的代码部分加锁,可以提高执行效率。
//双重校验锁
public class SingletonDemo3 {
private volatile static SingletonDemo3 instance;
private SingletonDemo3(){
}
public static SingletonDemo3 getInstance(){
if(instance == null){
synchronized (SingletonDemo3.class) {
if(instance == null){
instance = new SingletonDemo3();
}
}
}
return instance;
}
}
静态内部类实现
//静态内部类
public class SingletonDemo4 {
private static class SingletonClassInstance {
private static final SingletonDemo4 instance = new SingletonDemo4();
}
private SingletonDemo4(){
}
public static SingletonDemo4 getInstance(){
return SingletonClassInstance.instance;
}
}
外部类没有static属性,则不会像饿汉式那样立即加载对象。
只有真正调用getInstance(),才会加载静态内部类。加载类时是线程 安全的。 instance是static final类型,保证了内存中只有这样一个实例存在,而且只能被赋值一次,从而保证了线程安全性.
兼备了并发高效调用和延迟加载的优势!
枚举
public enum SingletonDemo5 {
/**
* 定义一个枚举的元素,它就代表了Singleton的一个实例。
*/
INSTANCE;
/**
* 单例可以有自己的操作
*/
public void singletonOperation(){
//功能处理
}
}
•优点:
–实现简单
–枚举本身就是单例模式。由JVM从根本上提供保障!避免通过反射和反序列化的漏洞!
•缺点:
–无延迟加载
总结
篇中对单例模式进行了简单介绍,同时介绍了它的五种典型的实现方式