单例模式
优点:内存中只有一个实例,减少内存开销;可以避免对资源的多重占用;设置全局访问点,严格控制访问
缺点:没有接口难以扩展,如需要扩展只有修改代码
设计重点:
1、私有化构造器
2、延迟加载
3、保证线程安全
4、防止序列化与反序列化攻击
5、防止反射攻击
饿汉式单例
在单例类首次被加载的时候就创建实例,重写readResolve()方法可以防止序列化与反序列化的攻击,无法防止反射攻击,只有在构造函数中进行对象非空判断, 缺点:浪费内存空间
public class HungerSingleton {
private static final HungerSingleton hungerSingleton = new HungerSingleton();
private HungerSingleton() {
}
public HungerSingleton getInstance() {
return hungerSingleton;
}
public Object readResolve() {
return hungerSingleton;
}
}
public class HungerStaticSingleton {
private static final HungerStaticSingleton HUNGER_STATIC_SINGLETON;
static {
HUNGER_STATIC_SINGLETON = new HungerStaticSingleton();
}
private HungerStaticSingleton() {
}
public HungerStaticSingleton getInstance() {
return HUNGER_STATIC_SINGLETON;
}
}
public class SerializableHungerSingletonTest {
public static void main(String[] args) {
HungerSingleton hungerSingleton1 = null;
HungerSingleton hungerSingleton2 = HungerSingleton.getInstance();
FileOutputStream fos = null;
try {
fos = new FileOutputStream("HungerSingleton.obj");
ObjectOutputStream outputStream = new ObjectOutputStream(fos);
outputStream.writeObject(hungerSingleton2);
outputStream.flush();
outputStream.close();
FileInputStream fileInputStream = new FileInputStream("HungerSingleton.obj");
ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
hungerSingleton1 = (HungerSingleton) objectInputStream.readObject();
System.out.println(hungerSingleton1);
System.out.println(hungerSingleton2);
System.out.println(hungerSingleton1==hungerSingleton2);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}catch (ClassNotFoundException e){
e.printStackTrace();
}
}
}
测试结果:
com.tealala.pattern.singleton.hungerSingleton.HungerSingleton@36baf30c
com.tealala.pattern.singleton.hungerSingleton.HungerSingleton@36baf30c
true
懒汉式单例
该单例类只有被调用的时候才创建实例
public class LazySingleton {
private static LazySingleton LAZY_SINGLETON;
private LazySingleton() {
}
public synchronized static LazySingleton getInstance() {
if (LAZY_SINGLETON == null) {
LAZY_SINGLETON = new LazySingleton();
}
return LAZY_SINGLETON;
}
}
public class LazySingletonDoubleCheck {
private volatile static LazySingletonDoubleCheck lazySingletonDoubleCheck;
private LazySingletonDoubleCheck() {
}
/**
* cpu在执行时会转换成JVM指令执行
* 指令重排序问题,volatile
* 1、分配内存给对象
* 2、初始化对象
* 3、将初始化好的对象与内存建立连接,赋值
* 4、用户初次访问
* @return
*/
public synchronized static LazySingletonDoubleCheck getInstance() {
if (lazySingletonDoubleCheck == null) {
synchronized (LazySingletonDoubleCheck.class) {
if (lazySingletonDoubleCheck == null) {
lazySingletonDoubleCheck = new LazySingletonDoubleCheck();
}
}
}
return lazySingletonDoubleCheck;
}
}
public class LazySingletonInnerClass {
private LazySingletonInnerClass() {
if(InnerLazySingleton.lazySingletonInnerClass!=null){
throw new RuntimeException("不允许构建多个实例!!");
}
}
public static final LazySingletonInnerClass getInstance() {
return InnerLazySingleton.lazySingletonInnerClass;
}
/**
* 利用JVM底层的逻辑,避免了线程安全的问题
*/
private static class InnerLazySingleton {
private static final LazySingletonInnerClass lazySingletonInnerClass = new LazySingletonInnerClass();
}
}
public class LazySingletonTest {
public static void main(String[] args) {
LazySingleton lazySingleton = LazySingleton.getInstance();
LazySingleton lazySingleton2 = LazySingleton.getInstance();
System.out.println(lazySingleton.toString());
System.out.println(lazySingleton2.toString());
LazySingletonDoubleCheck lazySingletonDoubleCheck = LazySingletonDoubleCheck.getInstance();
LazySingletonDoubleCheck lazySingletonDoubleCheck2 = LazySingletonDoubleCheck.getInstance();
System.out.println(lazySingletonDoubleCheck.toString());
System.out.println(lazySingletonDoubleCheck2.toString());
LazySingletonInnerClass lazySingletonInnerClass = LazySingletonInnerClass.getInstance();
LazySingletonInnerClass lazySingletonInnerClass2 = LazySingletonInnerClass.getInstance();
System.out.println(lazySingletonInnerClass.toString());
System.out.println(lazySingletonInnerClass2.toString());
}
}
执行结果:
com.tealala.pattern.singleton.lazySingleton.LazySingleton@76ed5528
com.tealala.pattern.singleton.lazySingleton.LazySingleton@76ed5528
com.tealala.pattern.singleton.lazySingleton.LazySingletonDoubleCheck@2c7b84de
com.tealala.pattern.singleton.lazySingleton.LazySingletonDoubleCheck@2c7b84de
com.tealala.pattern.singleton.lazySingleton.LazySingletonInnerClass@3fee733d
com.tealala.pattern.singleton.lazySingleton.LazySingletonInnerClass@3fee733d
注册式单例
将每一个实例都缓存到统一的容器中,使用唯一标识获取实例,(枚举类可以防止反射攻击和序列化与反序列化攻击)
public enum LazySingleRegister {
INSTANCE;
private Object Data;
public Object getData() {
return Data;
}
public void setData(Object data) {
Data = data;
}
public static LazySingleRegister getInstance() {
return INSTANCE;
}
}
public class LazySingleContainer {
private LazySingleContainer() {
}
private static Map<String, Object> ioc = new ConcurrentHashMap<String, Object>();
public static Object getBean(String className) {
synchronized (ioc) {
if (!ioc.containsKey(className)) {
Object obj = null;
try {
obj = Class.forName(className).newInstance();
ioc.put(className, obj);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return obj;
}
return ioc.get(className);
}
}
}
public class ThreadLocalSingleton {
private ThreadLocalSingleton() {
}
private static final ThreadLocal<ThreadLocalSingleton> THREAD_LOCAL = new ThreadLocal<ThreadLocalSingleton>() {
@Override
protected ThreadLocalSingleton initialValue() {
return new ThreadLocalSingleton();
}
};
public static ThreadLocalSingleton getInstance() {
return THREAD_LOCAL.get();
}
}