1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > 图灵学院java架构师VIP课程学习总结

图灵学院java架构师VIP课程学习总结

时间:2019-01-02 17:55:58

相关推荐

图灵学院java架构师VIP课程学习总结

最近加入了图灵学院java架构师的学习,着重学习高并发分布式核心架构技术学习,觉得很不错,分享架构大纲和总结的设计模式给大家,想要提升的同学可以在这些方面下点功夫,

课程资料

一:概念及理解

二、单例分类及详解

1、饿汉式单例

2、懒汉式单例

3、注册式单例

4、ThreadLocal单例

单例模式小结:

单例模式关键点:

一:概念及理解

单例模式(Singleton Pattern)是指确保一个类在任何情况下都绝对只有一个实例,并提供一个全局访问点。单例模式是创建型模式。常见单例举例:ServletContext、ServletContextConfig ;在 Spring 框架应用中 ApplicationContext;数据库的连接池DBPool也都是单例形式。优点:在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例。避免对资源的多重占用。缺点:没有接口,不能继承,要修改只能修改代码单例共有特征:

构造方法私有化(保证对象只能自己来创建)

自己在内部创建自己的实例

提供一个全局的访问点(一般是static方法)是拿到单例的入口

二、单例分类及详解

1、饿汉式单例

在单例类首次加载时就立即初始化,并且创建单例对象。不管有没有使用,先创建了再说。

public class HungrySingleton {//先静态、后动态//先属性、后方法//先上后下private static final HungrySingleton hungrySingleton = new HungrySingleton();//构造方法私有化private HungrySingleton(){}//static全局访问点public static HungrySingleton getInstance(){return hungrySingleton;}}

第二种饿汉式单例写法:利用static方法块,在类加载时就构建了唯一对象;

public class HungryStaticSingleton {private static final HungryStaticSingleton hungrySingleton;static {hungrySingleton = new HungryStaticSingleton();}private HungryStaticSingleton(){}public static HungryStaticSingleton getInstance(){return hungrySingleton;}}

优点:没有加任何的锁、执行效率比较高,在用户体验上来说,比懒汉式更好。

缺点:类加载的时候就初始化,不管用与不用都占着空间,浪费内存空间,如果从来没有使用也都创建了,小范围内影响不大,但是大范围使用不建议使用。

为了改善内存浪费,我们可以在使用到单例实例时再创建,这就时下面的懒汉式单例

2、懒汉式单例

特点:当用户要使用单例时才创建对象。(线程不安全)

//懒汉式单例//在外部需要使用的时候才进行实例化public class LazySimpleSingleton {private LazySimpleSingleton(){}//静态块,公共内存区域private static LazySimpleSingleton lazy = null;public static LazySimpleSingleton getInstance(){if(lazy == null){lazy = new LazySimpleSingleton();}return lazy;}}

以上懒汉式单例的实现是线程不安全的,并发环境下很可能出现多个Singleton实例,不同线程进入到if判断语句当中时,会出现创建多个不同实例的情况,偏离单例设计模式的初衷。

改进方法:通过synchronized来解决。

第一种:在getInstance方法上加同步synchronized(线程安全)

public synchronized static LazySimpleSingleton getInstance(){if(lazy == null){lazy = new LazySimpleSingleton();}return lazy;}

缺点:在getInstance方法上用synchronized 加锁,在线程数量比较多情况下,如果 CPU 分配压力上升,会导致大批量线程出现阻塞,从而导致程序运行性能大幅下降。于是下面第二种是更好的方式,既兼顾线程安全又提升程序性能

第二种:双重检查锁的单例模式,在getSingleton方法中对singleton进行两次判空。(线程安全)

public static LazyDoubleCheckSingleton getInstance(){if(lazy == null){synchronized (LazyDoubleCheckSingleton.class){if(lazy == null){lazy = new LazyDoubleCheckSingleton();}}}return lazy;}

更优方案:synchronized 关键字,总归是要上锁,对程序性能还是存在一定影响的。以下采用静态内部类的方式:

第三种:静态内部类方式(内部类先于外部类加载,调用getInstance方法时,内部类逻辑才会执行。性能最优的写法)(线程安全)

//这种形式兼顾饿汉式的内存浪费,也兼顾 synchronized 性能问题//完美地屏蔽了这两个缺点public class LazyInnerClassSingleton {//默认使用 LazyInnerClassGeneral 的时候,会先初始化内部类//如果没使用的话,内部类是不加载的private LazyInnerClassSingleton(){}//每一个关键字都不是多余的//static 是为了使单例的空间共享//保证这个方法不会被重写,重载public static final LazyInnerClassSingleton getInstance(){//在返回结果以前,一定会先加载内部类return LazyHolder.LAZY;}//默认不加载private static class LazyHolder{private static final LazyInnerClassSingleton LAZY = new LazyInnerClassSingleton();}}

高级内容:(这里只做大概说明,具体可参考我头部链接一起学习)

反射破坏单例

我们前面所介绍的,单例模式必须满足构造方法私有化,避免外部实例化,而Java反射机制是能够实例化构造方法为private的类的,使所有的Java单例实现失效。

解决办法:在构造函数中抛出异常,提醒开发人员,不允许用反射机制创建单例。

private LazyInnerClassSingleton(){if(LazyHolder.LAZY != null){throw new RuntimeException("不允许创建多个实例");}}

序列化破坏单例

当我们将一个单例对象创建好,序列化然后写入到磁盘,下次使用时再从磁盘中读取到对象,反序列化转化为内存对象。反序列化后的对象会重新分配内存,即重新创建。那如果序列化的目标的对象为单例对象,就违背了单例模式的初衷,相当于破坏了单例。

解决办法:在单例类中加上以下方法,覆盖了序列化对象,反序列化出来的对象,还是创建了两次,发生在JVM层次,之前反序列化出来的对象被GC回收。

private Object readResolve(){return INSTANCE;}

3、注册式单例

解决了序列化问题,最安全单例;

每一个实例都登记到某一个地方,使用唯一的标识获取实例,一种为容器缓存,一种为枚举登记,下面介绍其中一种;

//枚举式单例public enum EnumSingleton {INSTANCE;private Object data;public Object getData() {return data;}public void setData(Object data) {this.data = data;}public static EnumSingleton getInstance(){return INSTANCE;}}

4、ThreadLocal单例

ThreadLocal 不能保证其创建的对象是全局唯一,但是能保证在单个线程中是唯一的,天生的线程安全。

public class ThreadLocalSingleton {private static final ThreadLocal<ThreadLocalSingleton> threadLocalInstance =new ThreadLocal<ThreadLocalSingleton>(){@Overrideprotected ThreadLocalSingleton initialValue() {return new ThreadLocalSingleton();}};private ThreadLocalSingleton(){}public static ThreadLocalSingleton getInstance(){return threadLocalInstance.get();}}

单例模式小结:

单例模式可以保证内存里只有一个实例,减少了内存开销;可以避免对资源的多重占用。

单例模式关键点:

构造函数方法为Private修饰。通过一个静态方法或者枚举返回单例类对象。需要确保单例类的对象有且只有一个,尤其是在多线程环境下。确保单例类对象在反序列化时不会重新构建对象。

重点掌握饿汉式与懒汉式两种单例模型。

饿汉式:不用也加载。线程安全的,可以直接用于多线程而不会出现问题,但会出现内存浪费情况,不推荐大范围使用

懒汉式:用时再加载。非线程安全,可通过getInstance方法上加同步synchronized、双重检查锁、静态内部类三种方式改善;

其中第一种每次都同步,性能不好,第二种两次非空检查,避免每次同步的性能损耗,第三种没有性能损耗。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。