简介
单例模式,是一种常用的软件设计模式,在它的核心结构中只包含一个被称为单例的特殊类。
通过单例模式可以保证系统中,应用该模式的类一个类只有一个实例。即一个类只有一个对象实例
使用场景
-在我们创建一个对象需要消耗过多的资源时,便可以考虑使用单例模式
例如:图片加载框架ImageLoader,ImageLoader中含有线程池、缓存系统、网络请求等,如果每次使用都要创建一个对象,这样会消耗很多资源,这是我们可以考虑使用单例模式。
-需要频繁的实例化然后销毁的对象
-频繁访问数据库或文件的对象
-需要定义大量的静态常量和静态方法(例如工具类)
1.懒汉式(线程不安全)
public class Singleton {
private static Singleton singleton = null;
private Singleton() {
}
public static Singleton getInstance() {
if (singleton == null) {
singleton = new Singleton();
}
return singleton;
}
}
优点:第一次调用才初始化,避免内存浪费。
缺点:多线程同时调用,会出现多个实例,相对不安全。
2.懒汉式(线程安全)
public class Singleton {
private static Singleton singleton;
private Singleton(){
}
public static synchronized Singleton getInstance() {
if (singleton == null) {
singleton = new Singleton();
}
return singleton;
}
}
优点:线程安全
缺点:多线程同时使用时,数据不需要同步时,效率比较低
3.饿汉式
public class Singleton {
private static Singleton singleton = new Singleton();
private Singleton(){}
public static Singleton getInstance() {
return singleton;
}
}
优点:类加载初始化时就创建好一个静态的对象供外部使用,避免多线程环境下执行getInstance出现不同实例。
缺点:类加载时就初始化,浪费内存。
4.双重校验模式
public class Singleton {
private volatile static Singleton singleton;
private Singleton(){
}
public static Singleton getInstance() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
优点:避免不必要的同步,线程安全
缺点:在JDK1.5之后,双重检验锁才能达到单利的效果
5.静态内部类
public class Singleton {
private Singleton(){
}
public static Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
private static class SingletonHolder{
private static final Singleton INSTANCE= new Singleton();
}
}
有点:类被加载了,intstance不会被实例化,调用getInsatnce才会产生实例,实现了延迟加载
6.枚举
public enum Singleton{
INSTANCE;
public void doWork() {
}
}
它不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象,非常推荐使用
7.使用Map管理
public class SingletonManager {
private static Map<String, Object> instanceMap = new HashMap<String,Object>();//使用HashMap作为缓存容器
private Singleton() {
}
public static void registerInstance(String key, Object instance) {
if (!instanceMap.containsKey(key) ) {
instanceMap.put(key, instance) ;
}
}
public static Object getInstance(String key) {
return instanceMap.get(key) ;
}
}
总结
以上的就是几种常见的单利模式,根据项目中单例的使用场景来选择使用哪种方式。