介绍
单例模式是一种对象创建的方式,特点是一个类只负责创建自己的对象,而且只保证创建一个,同时只提供一直访问方式。
实现
Demo:
public class SingletonBean {
//由当前类创建一个Singleton的对象
private static SingletonBean singletonBean = new SingletonBean();
//将构造函数私有化,该类就不会实例化
private SingletonBean(){}
//对外提供一个获取唯一对象的方法
public static SingletonBean getInstance(){
return singletonBean;
}
}
public class SingletonPattern {
public static void main(String[] args) {
SingletonBean instance = SingletonBean.getInstance();
}
}
单例模式的几种实现:
1、饿汉模式
优点:没有加锁,效率高;同时利用classloader的机制避免了线程同步的问题。
缺点:类装载时就初始化,导致产生垃圾对象浪费内存。
public class SingletonBean {
//类装载时就会初始化,所以如果该类有其他静态方法或者属性被调用,该对象就会被实例化
private static SingletonBean singletonBean = new SingletonBean();
private SingletonBean(){}
//对外提供一个获取唯一对象的方法
public static SingletonBean getInstance(){
return singletonBean;
}
}
2、懒汉模式
优点:无,不建议使用这种方式。
缺点:在多线程的情况下,不能保证正常工作。
public class SingletonBean {
private static SingletonBean singletonBean;
private SingletonBean(){}
public static SingletonBean getInstance(){
//再多线程的情况下,会多次实例化
/** 比如:线程A进来判断singletonBean ==null 为true,在new SingletonBean之前线程B 进来,
这时singletonBean ==null 还是为true的。所以会导致A、B都执行了 new SingletonBean();**/
if (singletonBean == null){
return new SingletonBean();
}
return singletonBean;
}
}
3、懒汉安全模式
优点:第一次调用才会被创建,相比较饿汉的方式,节省空间。
缺点:每次访问获取对象时加synchronized,效率低。
public class SingletonBean {
private static SingletonBean singletonBean;
private SingletonBean(){}
public static synchronized SingletonBean getInstance(){
if (singletonBean == null){
return new SingletonBean();
}
return singletonBean;
}
}
4、双重校验模式
优点: 比较第三种懒汉安全模式来说,只是在需要实例化的时候加锁,效率上高了很多;而且需要对singletonBean 加volatile修饰符,保证对象被实例化后其他线程立即可见。
public class SingletonBean {
private volatile static SingletonBean singletonBean;
private SingletonBean() {
}
public static SingletonBean getInstance() {
if (singletonBean == null) {
synchronized (SingletonBean.class) {
if (singletonBean == null) {
return new SingletonBean();
}
}
}
return singletonBean;
}
}
5、静态内部类
优点:相比较恶汉模式,这种模式SingletonBean类装载并不会导致初始化,而且同样采用了classloader的机制来保证线程安全
public class SingletonBean {
private static class SingletonBeanHolder{
private static final SingletonBean SINGLETON_BEAN = new SingletonBean();
}
private SingletonBean() {
}
public static final SingletonBean getInstance() {
return SingletonBeanHolder.SINGLETON_BEAN;
}
}
6、枚举
这种方式工作中并不常用,但是这种方式确实是最简洁的。
public enum SingletonBean {
INSTANCE;
}
最后
建议不使用懒汉模式2、3,使用恶汉模式1,其中分情况,如果需要指定懒加载的话使用5,其他大多数情况使用4
参考:<菜鸟教程>
网友评论