内容定位
-
听说过单列模式,但不知道如何应用的人群
-
单列模式是非常经典的高频面试题,希望通过面试单列彰显技术深度,顺利拿到Offer的人群。
-
听说过原型模式,但不知道如何应用的人群
-
单列模式(Singleton Pattern)是指确保一个在任何情况下都绝对只有一个实列,并提供一个全局访问点。
隐藏其所有的构造方法。
属于创建型模式。确保任何情况下都绝对只有一个实列。
ServletContext 、 ServletConfig 、 ApplicationContext 、 DBPool
-
饿汉式单例
在单例类首次加载时就创建实列。private static HungerySingleton hungerySingleton = new HungerySingleton(); private HungerySingleton(){ } public static HungerySingleton getInstance(){ return hungerySingleton; } }
private static HungerySingleton hungerySingleton ; static { hungerySingleton = new HungerySingleton(); } private HungerySingleton(){ } public static HungerySingleton getInstance(){ return hungerySingleton; } }
缺点: 浪费内存空间。
-
懒汉式单例
解决浪费内存空间的问题public class LazySimpleSingleton{ private static LazySimpleSingleton lazy = null; private LazySimpleSingleton() { } public static LazySimpleSingleton getInstance() { if (null == lazy) { lazy = new LazySimpleSingleton(); } return lazy; } }
public class LazySimpleSingleton{ private static LazySimpleSingleton lazy = null; private LazySimpleSingleton() { } public static synchronized LazySimpleSingleton getInstance() { if (null == lazy) { lazy = new LazySimpleSingleton(); } return lazy; } }
public class ExectorThread immplements Runnable {
public void run () {
LazySimpleSingleton singleton = LazySimpleSingleton.getInstance();
System.out.println( Thread.currentThread().getName() + ":" + singleton);
}
}
双重检查锁` :解决synchronized在静态方法上的性能问题
public class LazyDoubleCheckSingleton{
private static LazyDoubleCheckSingletonlazy lazy = null;
private LazyDoubleCheckSingleton() {
}
public static LazyDoubleCheckSingletongetInstance() {
if (null == lazy) {
synchronized() {
if (null == lazy) {
l azy = new LazyDoubleCheckSingleton();
// CPU 执行时候会转换成 JVM指令执行
// 1 . 分配内存给这个对象
// 2. 初始化对象
// 3. 将初始化好的对象和内存地址建立管理,赋值
// 4. 用户初次访问
}
}
return lazy;
}
}
public static void main(String[] args) {
Thread t1= new Thread(new ExectorThread());
Thread t2 = new Thread(new ExectorThread());
t1.start();
t2.start();
}
静态内部类
// 全程没有synchronized
// 性能最优的一种写法
public class LazyInnerClassSingleton{
// 虽然构造方法私有,但是,逃不过反射的法眼
private LazyInnerClassSingleton(){}
// LazyHolder 里面的逻辑需要等到外部方法调用时才执行
// 巧妙的利用了内部类的特性
// JVM底层执行逻辑,完美地避免了线程安全问题
public static final LazyInnerClassSingleton getInstance() {
return LazyHolder .LAZY;
}
private static class LazyHolder {
private static final LazyInnerClassSingleton LAZY = new LazyInnerClassSingleton();
}
}
public class SeriableSingleton {
private SeriableSingleton () {}
private final static SeriableSingleton INSTANCE = new SeriableSingleton();
public static SeriableSingleton getInstance(){
return INSTANCE;
}
private Object readResolve() {
return INSTANCE;
}
}
重新readResolve 方法,只不是覆盖了反序列化处理的对象,还是创建了两次,发生在 JVM层面,相对来说比较安全。
- 注册式单例: 将每一个实列都缓存到统一的容器中,使用唯一标识获取实列
枚举式单列
public enum EnumSingleton{
INSTANCE;
private Object data;
// getter setter
public static EnumSingleton getInstance() {
return INSTANCE;
}
}
public class EnumSingletonTest{
public static void main(String[] args){
}
}
-
ThreadLocal 单例
-
注册登记式:
public classs ContainerSingleton{
private static Map<String,Object> ioc = new ConcurrentHashMap();
public static <T> T getInstance(String className){
synchronized(ioc){
if(ioc.containerKey(className)) {
return (T)ioc.get(className);
}
try {
Object instance =Class.forName(className).newInstance();;
ioc.put(className,instance);
}catch(Exception e) {
e.printStacks();
}
return (T)ioc.get(className);
}
}
}
ConcurrentExecutor.execute(new RunHandler(){
public void handler(){
}
},10, 6)
原型模式: 就是如何快速构建对象方法总结,
简单工厂将getter,setter封装到某个方法中
JDK提供的实现Cloneable接口,实现快速复制
scope=“prototype” scope=“singleton”
BeanUtils.copyOf()
JONS.parseObject()
欢迎做技术交流: