要点:(1)各个类都只有一个实例。(2)它必须自行创建这个唯一实例。(3)它必须自行向其他对象提供该实例。
本质:控制实例的数量。
应用场景:线程池、缓存、日志对象、对话框、打印机、显卡的驱动程序对象等。
(二)单例模式主要分为:懒汉式单例、饿汉式单例两种。
1. 懒汉式(延迟加载法):以时间换空间
public class Singleton {
//1.收回外部实例化Singleton类的权限
private Singleton(){};
//3.声明一个静态对象来保存实例
private static Singleton single = null;
//2.主动向外部提供获取该实例的方法
public static Singleton getInstance()
{
//4.判断实例是否已实例化
if(single == null)
{
//5.未实例化则实例化
single = new Singleton();
}
return single;
}
}
优点:资源利用率高,不执行getInstance就不会被实例。
缺点:线程不安全,并发环境下可能出现多个实例。
改进方案:
public class Singleton {
//1.收回外部实例化Singleton类的权限
private Singleton(){};
//3.声明一个静态对象来保存实例
private static Singleton single = null;
//2.主动向外部提供获取该实例的方法(加上synchronized锁达到线程安全)
public static synchronized Singleton getInstance()
{
//4.判断实例是否已实例化
if(single == null)
{
//5.未实例化则实例化
}
return single;
}
}
缺点:synchronized的使用增加了不必要的资源开销。
2. 饿汉式(预先加载法):以空间换时间
public class Singleton {
//1.收回外部实例化Singleton类的权限
private Singleton(){};
//3.运行即初始化实例
private static Singleton single = new Singleton();
//2.主动向外部提供获取该实例的方法
public static Singleton getInstance()
{
return single;
}
}
优点:线程安全;运行即进行初始化,所以调用实例速度快。
缺点:资源利用率不高,可能存在永远用不到的实例。
测试:
public class main {
public static void main(String []args)
{
Singleton single1 = Singleton.getInstance(); //获取实例1
Singleton single2 = Singleton.getInstance(); //获取实例2
if(single1 == single2) //判断两个实例是否是同一实例
{
System.out.print("同一实例");
}
else
{
System.out.print("不同实例");
}
}
}
运行结果:同一实例