饿汉式单例
-
示例:
- JDK:
Runtime.getRuntime()
(饿汉式) - Spring:
DefaultSingletonBeanRegistry
(通过 ConcurrentHashMap 管理单例 Bean)
- JDK:
//饿汉式单例
public class HungerSingleton implements Serializable {
private static final HungerSingleton INSTANCE=new HungerSingleton();
private HungerSingleton(){
//防止反射破坏单例
if (INSTANCE!=null){
throw new RuntimeException("禁止反射攻击");
}
}
public static HungerSingleton getINSTANCE(){
return INSTANCE;
}
//防止序列化破坏单例,单例类中定义private Object readResolve()方法, 方法返回单例对象。因为在反序列化时如果类中有个叫readResolve的方法,就会执行这个方法并返回结果。
protected Object readResolve(){
return INSTANCE;
}
}
双重检查锁
public class DCLSingleton {
private static volatile DCLSingleton instance;
private DCLSingleton(){
if (instance!=null){
throw new IllegalStateException("禁止反射破坏单例模式");
}
}
public static DCLSingleton getInstance(){
if (instance==null){
synchronized (DCLSingleton.class){
if (instance==null){
instance=new DCLSingleton();
}
}
}
return instance;
}
}
枚举
public enum EnumSingleton {
INSTANCE;
}
静态内部类方式
public class StaticClassSingleton {
private StaticClassSingleton(){
if (internalClass.INSTANCE!=null){
throw new IllegalStateException("禁止反射破坏单例");
}
}
static class internalClass{
static final StaticClassSingleton INSTANCE=new StaticClassSingleton();
}
public static StaticClassSingleton getInstance(){
return internalClass.INSTANCE;
}
}
尝试破坏单例模式
public class DestorySingletonTest {
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
//反射破坏单例模式
reflection();
//序列化破坏单例模式
// serialization();
}
private static void serialization() {
HungerSingleton instance = HungerSingleton.getInstance();
try {
//序列化
ObjectOutput output=new ObjectOutputStream(new FileOutputStream("singleton.ser"));
output.writeObject(instance);
output.close();
//反序列化
ObjectInput input=new ObjectInputStream(new FileInputStream("singleton.ser"));
HungerSingleton o = (HungerSingleton) input.readObject();
input.close();
System.out.println(instance.hashCode());
System.out.println(o.hashCode());
System.out.println(instance==o);
} catch (IOException e) {
throw new RuntimeException(e);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
private static void reflection() throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
Constructor<HungerSingleton> constructor = HungerSingleton.class.getDeclaredConstructor();
constructor.setAccessible(true);
HungerSingleton hungerSingleton = constructor.newInstance();
System.out.println(HungerSingleton.getInstance()==hungerSingleton);
}
}