一、什么是单例、多例:
所谓单例就是所有的请求都用一个对象来处理,比如我们常用的service和dao层的对象通常都是单例的,而多例则指每个请求用一个新的对象来处理,比如action;
二、单例模式和多例模式说明:
- 单例模式和多例模式属于对象模式。
- 单例模式的对象在整个系统中只有一份,多例模式可以有多个实例。
- 它们都不对外提供构造方法,即构造方法都为私有。
三、单例模式适用场景:
- 需要生成唯一序列的环境
- 需要频繁实例化然后销毁的对象。
- 创建对象时耗时过多或者耗资源过多,但又经常用到的对象。
- 方便资源相互通信的环境
四、举例
1、懒汉式
你用的时候,我再去给你创建对象
class Singleton{
private static Singleton single;
private static Singleton(){}
public static synchronized Singleton getInstance(){
if(single==null)
single =new Singleton();
return single;
}
}
优点: 第一次调用才初始化,避免浪费内存
缺点: 加锁了执行效率低
2、饿汉式
启动的时候就创建了对象,
class SingleObj{
//私有变量
private static SingleObj single=new SingleObj();
//私有构造函数 不能被实例化
private static SingleObj(){}
public static SingleObj getInstance(){
return single;
}
}
优点: 没有加锁,执行效率更高
缺点: 类加载时就初始化,浪费内存
3、Double CheckLock实现单例:
Double CheckLock也就是双重锁判断机制(由于JVM底层模型原因,偶尔会出问题,
不建议使用),是在懒汉式单例上发展而来
/**
*Double CheckLock实现单例
*Double CheckLock也就是双重锁判断机制(由于JVM底层模型原因,
*偶尔会出问题,不建议使用)
*/
public class SingletonThree {
private volatile static SingletonThree instance;
//私有化构造器
private SingletonThree() {
}
//静态工厂方法,双重锁判断机制
public static SingletonThree newInstance() {
if (instance== null) {
synchronized (SingletonThree.class) {
if (instance== null) {
instance= new SingletonThree();
}
}
}
return instance;
}
}
4、静态内部类模式:
特点:线程安全,调用效率高,可以延时加载
/**
*静态内部类实现模式
*线程安全,调用效率高,可以延时加载
*/
public class SingletonFour {
// 静态内部类
private static class SingletonClassInstance {
private static final SingletonFour instance= new SingletonFour();
}
// 私有化构造器
private SingletonFour() {
}
//静态工厂方法
public static SingletonFour getInstance() {
return SingletonClassInstance.instance;
}
}
5、枚举类:
特点: 线程安全,调用效率高,不能延时加载,可以天然的防止反射和反序列化调用;
描述: 这种实现方式还没有被广泛采用,但这是实现单例模式的最佳方法。它更简洁,自动支持序列化机制,绝对防止多次实例化。
这种方式是 Effective Java 作者 Josh Bloch 提倡的方式,它不仅能避免多线程同步问题,而且还自动支持序列化机制,防止反序列化重新创建新的对象,绝对防止多次实例化。不过,由于 JDK1.5 之后才加入 enum 特性,用这种方式写不免让人感觉生疏,在实际工作中,也很少用。
不能通过 reflection attack 来调用私有构造方法。
public class SingletonFive {
//私有化构造器
private SingletonFive(){
}
//使用枚举
private static enum Singleton{
INSTANCE;
private SingletonFive singleton;
//JVM会保证此方法绝对只调用一次
private Singleton(){
singleton = new SingletonFive();
}
public SingletonFive getInstance(){
return singleton;
}
}
//静态工厂方法
public static SingletonFive getInstance(){
return Singleton.INSTANCE.getInstance();
}
}