单例模式
饿汉式
import java.io.Serializable;
/**`在这里插入代码片`
* Innertwo
*
*/
public class two implements Serializable{
private two(){
//防止反射 破环单例
if(INSTANCE != null){
throw new RuntimeException("error");
}
}
private static final two INSTANCE = new two();
public static two getIn() {
return INSTANCE;
}
//防止被反序列化 破坏单例
public Object readResolve(){
return INSTANCE;
}
}
可能会被Unsafe破坏单例
enum类型的饿汉式
public enum enumOne {
INSTANCE;
public static enumOne getInstance() {
return INSTANCE;
}
}
可能会被Unsafe破坏单例
懒汉式
import java.io.Serializable;
public class lanOne implements Serializable{
private lanOne(){};
private static lanOne INSTANCE = null;
public static lanOne getINSTANCE() {
if(INSTANCE == null){
INSTANCE = new lanOne();
}
return INSTANCE;
}
}
DCL懒汉式(双检锁)
public class lanOne implements Serializable{
private lanOne(){};
private static volatile lanOne INSTANCE = null;
public static lanOne getINSTANCE() {
if(INSTANCE == null){
synchronized(lanOne.class){
if(INSTANCE == null){
INSTANCE = new lanOne();
}
}
}
return INSTANCE;
}
}
为什么要加volatile?
在编译的代码 无关紧要的代码执行顺序是有可能被改变的,比如构造对象,和给对象赋值=。这两步是有可能被优化为先赋值,再构造对象。如果再多线程情况下,第一个线程赋值,但是还没构造对象,这时候第二个线程,直接执行return.那第二个线程拿到的对象是不完整的。
添加volatile以后,添加内存屏障,要求赋值之后不能进行构造操作,那么就只能先构造了。
内部类 懒汉式
public class innerClass {
private innerClass(){};
public static class holder{
static innerClass INSTANCE = new innerClass();
}
public static innerClass getINSTANCE() {
return holder.INSTANCE;
}
}
单例设计模式在jdk中的体现
- Runtime 饿汉式
- System 双检锁 懒汉式