定义:
保证一个类只有一个实例,并提供一个全局访问点。(创建型)
应用场景:
想确保任何情况下都绝对只有一个实例。
优点:
1.在内存只有一个实例,减少内存开销。
2.可以避免对资源的多重占用。
3.设置了全局的访问点,严格的控制访问
缺点:
没有接口,扩展比较困难,只能修改代码
重点:
1.私有构造器
2.线程安全
3.延迟加载
4.序列化和反序列化得安全
5.反射,防御反射攻击
Coding:
1.懒汉式(线程不安全):
public class LazySingleton {
private static LazySingleton instance = null;
private LazySingleton(){
}
/**
* 多线程不安全的
* @return
*/
public static LazySingleton getInstance(){
if(null == instance){
return new LazySingleton();
}
return instance;
}
}
2.懒汉式改进(通过加锁保证线程安全):
public class LazySynchronizedSingleton {
private static LazySynchronizedSingleton instance = null;
private LazySynchronizedSingleton() {
}
/**
* 改进方式--同步锁,多线程安全的(但是性能比较差)
*
* @return
*/
public synchronized static LazySynchronizedSingleton getInstance1() {
if (null == instance) {
return new LazySynchronizedSingleton();
}
return instance;
}
}
3.双重检测(线程不安全):
/**
* 双重检测
*/
public class LazyDoubleCheckSingleton {
private static LazyDoubleCheckSingleton instance = null;
private LazyDoubleCheckSingleton(){
}
/**
* 此种方法存在弊端
* @return
*/
public static LazyDoubleCheckSingleton getInstance(){
if(null == instance){
synchronized (instance) {
if(null == instance){
/**
* 1.给对象分配内存
* 2.初始化对象
* 3.设置instance 指向分配的内存地址
* 此处存在指令重排序的问题: 3可能在2之前执行
*/
new LazyDoubleCheckSingleton();
}
}
return instance;
}
return instance;
}
}
双重检测单例分析
分析:
线程0还没初始化对象时,线程1判断对象部位null,线程1可能会直接访问未初始化完成的对象,可能会导致异常。
4.双重检测改进(volatile 保证线程可见性):
/**
* 双重检测
*/
public class LazyDoubleCheckSingleton {
//线程可见,防止指令重排序
private volatile static LazyDoubleCheckSingleton instance = null;
private LazyDoubleCheckSingleton(){
}
/**
* 此种方法存在弊端
* @return
*/
public static LazyDoubleCheckSingleton getInstance(){
if(null == instance){
synchronized (instance) {
if(null == instance){
/**
* 1.给对象分配内存
* 2.初始化对象
* 3.设置instance 指向分配的内存地址
* 此处存在指令重排序的问题: 3可能在2之前执行
*/
new LazyDoubleCheckSingleton();
}
}
return instance;
}
return instance;
}
}
5.静态内部类-单例(利用类的初始化):
/**
* 静态内部类创建单例对象
*/
public class StaticInnerClassSingleton {
/**
* 静态内部类
*/
private static class InnerClass {
private static StaticInnerClassSingleton staticInnerClassSingleton = new StaticInnerClassSingleton();
}
public static StaticInnerClassSingleton getInstance(){
return InnerClass.staticInnerClassSingleton;
}
private StaticInnerClassSingleton(){
}
}
6.饿汉式:
/**
* 饿汉式--类加载的时候就初始化好了
*/
public class HungrySignleton {
private HungrySignleton(){
}
private static final HungrySignleton INSTANCE = new HungrySignleton();
public static HungrySignleton getInstance(){
return INSTANCE;
}
}
微信公众号欢迎关注.jpg
网友评论