范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

java性能优化实战如何用设计模式进行性能优化

  #头条创作挑战赛#
  代码的结构对应用的整体性能,有着重要的影响。结构优秀的代码,可以避免很多潜在的性能问题,在代码的扩展性上也有巨大的作用;结构清晰、层次分明的代码,也有助于帮你找到系统的瓶颈点,进行专项优化。
  设计模式  就是对常用开发技巧进行的总结,它使得程序员之间交流问题,有了更专业、便捷的方式。比如,我们在《02 | 理论分析:性能优化有章可循,谈谈常用的切入点》中提到,I/O 模块使用的是装饰器模式,你就能很容易想到 I/O 模块的代码组织方式。
  事实上,大多数设计模式并不能增加程序的性能,它只是代码的一种组织方式。本课时,我们将一一举例讲解和性能相关的几个设计模式,包括代理模式、单例模式、享元模式、原型模式等。  如何找到动态代理慢逻辑的原因?
  Spring 广泛使用了代理模式,它使用 CGLIB 对 Java 的字节码进行了增强。在复杂的项目中,会有非常多的 AOP 代码,比如权限、日志等切面。在方便了编码的同时,AOP 也给不熟悉项目代码的同学带来了很多困扰。
  下面我将分析一个  使用 arthas 找到动态代理慢逻辑的具体原因  ,这种方式在复杂项目中,非常有效,你不需要熟悉项目的代码,就可以定位到性能瓶颈点。
  首先,我们创建一个最简单的 Bean(代码见仓库)。  @Component  public class ABean {      public void method() {          System.out.println("*******************");      }  }
  然后,我们使用 Aspect 注解,完成切面的书写,在前置方法里,我们让线程 sleep 了 1 秒钟。  @Aspect  @Component  public class MyAspect {      @Pointcut("execution(* com.github.xjjdog.spring.ABean.*(..)))")      public void pointcut() {      }       @Before("pointcut()")      public void before() {          System.out.println("before");          try {              Thread.sleep(TimeUnit.SECONDS.toMillis(1));          } catch (InterruptedException e) {              throw new IllegalStateException();          }      }  }
  创建一个 Controller,当访问 /aop 链接时,将会输出 Bean 的类名称,以及它的耗时。  @Controller  public class AopController {      @Autowired      private ABean aBean;       @ResponseBody      @GetMapping("/aop")      public String aop() {          long begin = System.currentTimeMillis();          aBean.method();          long cost = System.currentTimeMillis() - begin;          String cls = aBean.getClass().toString();          return cls + " | " + cost;      }  }
  执行结果如下,可以看到 AOP 代理已经生效,内存里的 Bean 对象,已经变成了EnhancerBySpringCGLIB 类型,调用方法 method,耗时达到了1023ms。  class com.github.xjjdog.spring.ABean$EnhancerBySpringCGLIB$a5d91535 | 1023
  下面使用 arthas 分析这个执行过程,找出耗时最高的 AOP 方法。启动 arthas 后,可以从列表中看到我们的应用程序,在这里,输入 2 进入分析界面。
  在终端输入 trace 命令,然后访问 /aop 接口,终端将打印出一些 debug 信息,可以发现耗时操作就是 Spring 的代理类。  trace com.github.xjjdog.spring.ABean method
  代理模式
  代理模式(Proxy)可以通过一个代理类,来控制对一个对象的访问。
  Java 中实现动态代理主要有两种模式:一种是使用 JDK,另外一种是使用 CGLib。  其中,JDK 方式是面向接口的,主 要的相关类是 InvocationHandler 和 Proxy;  CGLib 可以代理普通类,主要的相关类是 MethodInterceptor 和 Enhancer。
  这个知识点面试频率非常高  ,仓库中有这两个实现的完整代码,这里就不贴出来了。
  下面是 JDK 方式和 CGLib 方式代理速度的 JMH 测试结果:  Benchmark              Mode  Cnt      Score      Error   Units  ProxyBenchmark.cglib  thrpt   10  78499.580   1771.148  ops/ms  ProxyBenchmark.jdk    thrpt   10  88948.858    814.360  ops/ms
  我现在用的   JDK   版本是 1.8,可以看到,CGLib 的速度并没有传得那么快(有传言高出10 倍),相比较而言,它的速度甚至略有下降。 我们再来看下  代理  的创建速度,结果如下所示。可以看到,在代理类初始化方面,JDK 的吞吐量要高出 CGLib 一倍。  Benchmark                    Mode  Cnt      Score      Error   Units  ProxyCreateBenchmark.cglib  thrpt   10   7281.487   1339.779  ops/ms  ProxyCreateBenchmark.jdk    thrpt   10  15612.467    268.362  ops/ms
  综上所述,JDK 动态代理和 CGLib 代理的创建速度和执行速度,在新版本的 Java 中差别并不是很大,Spring 选用了 CGLib,主要是因为它能够代理普通类的缘故。  单例模式
  Spring 在创建组件的时候,可以通过 scope 注解指定它的作用域,用来标示这是一个prototype(多例)还是 singleton(单例)。
  当指定为单例时(默认行为),在 Spring 容器中,组件有且只有一份,当你注入相关组件的时候,获取的组件实例也是同一份。
  如果是普通的单例类,我们通常将单例的构造方法设置成私有的,单例有懒汉加载和饿汉加载模式。
  了解 JVM 类加载机制的同学都知道,一个类从加载到初始化,要经历 5 个步骤:加载、验证、准备、解析、初始化。
  其中,static 字段和 static 代码块,是属于类的,在类加载的初始化阶段就已经被执行。它在字节码中对应的是 方法,属于类的(构造方法)。因为类的初始化只有一次,所以它就能够保证这个加载动作是线程安全的。
  根据以上原理,只要把单例的初始化动作,放在方法里,就能够实现  饿汉模式  。  private static Singleton instace = new Singleton();
  饿汉模式在代码里用得很少,它会造成资源的浪费,生成很多可能永远不会用到的对象。 而对象初始化就不一样了。通常,我们在 new 一个新对象的时候,都会调用它的构造方法,就是,用来初始化对象的属性。由于在同一时刻,多个线程可以同时调用函数,我们就需要使用 synchronized 关键字对生成过程进行同步。
  目前,  公认的兼顾线程安全和效率的单例模式,就是 double check。很多面试官,会要求你手写,并分析 double check 的原理。
  如上图,是 double check 的关键代码,我们介绍一下四个关键点:  第一次检查,当 instance 为 null 的时候,进入对象实例化逻辑,否则直接返回。  加同步锁,这里是类锁。  第二次检查才是关键。如果不加这次判空动作,可能会有多个线程进入同步代码块,进而生成多个实例。  最后一个关键点是 volatile 关键字。在一些低版本的 Java 里,由于指令重排的缘故,可能会导致单例被 new 出来后,还没来得及执行构造函数,就被其他线程使用。 这个关键字,可以阻止字节码指令的重排序,在写 double check 代码时,习惯性会加上 volatile。
  可以看到,  double check 的写法繁杂,注意点很多,它现在其实是一种反模式,已经不推荐使用了  ,我也不推荐你用在自己的代码里。但它能够考察面试者对并发的理解,所以这个问题经常被问到。
  推荐使用 enum 实现懒加载的单例,代码片段如下:
  《Effective Java》这本书也同样推荐了该方式。  public class EnumSingleton {      private EnumSingleton() {      }      public static EnumSingleton getInstance() {          return Holder.HOLDER.instance;      }      private enum Holder {          HOLDER;          private final EnumSingleton instance;          Holder() {              instance = new EnumSingleton();          }      }  }  享元模式
  享元模式(Flyweight)是难得的,专门针对性能优化的设计模式,它通过共享技术,最大限度地复用对象。享元模式一般会使用唯一的标识码进行判断,然后返回对应的对象,使用 HashMap 一类的集合存储非常合适。
  上面的描述,我们非常熟悉,因为在过去的一些课时中,我们就能看到很多享元模式的身影,比如《09 | 案例分析:池化对象的应用场景》里的池化对象和《10 | 案例分析:大对象复用的目标和注意点》里的对象复用等。
  设计模式对这我们平常的编码进行了抽象,从不同的角度去解释设计模式,都会找到设计思想的一些共通点。比如,单例模式就是享元模式的一种特殊情况,它通过共享 单个实例 ,达到对象的复用。
  值得一提的是,同样的代码,不同的解释,会产生不同的效果。比如下面这段代码: Map strategys = new HashMap<>();  strategys.put("a",new AStrategy());  strategys.put("b",new BStrategy());
  如果我们从对象复用的角度来说,它就是享元模式;如果我们从对象的功能角度来说,那它就是策略模式。所以大家在讨论设计模式的时候,一定要注意上下文语境的这些差别。 原型模式
  原型模式(Prototype)比较类似于复制粘贴的思想,它可以首先创建一个实例,然后通过这个实例进行新对象的创建。在 Java 中,最典型的就是  Object 类的 clone 方法 。
  但编码中这个方法很少用,我们上面在代理模式提到的 prototype,并不是通过 clone 实现的,而是使用了更复杂的反射技术。
  一个比较重要的原因就是 clone 如果只拷贝当前层次的对象,实现的只是浅拷贝。在现实情况下,对象往往会非常复杂,想要实现深拷贝的话,需要在 clone 方法里做大量的编码,远远不如调用 new 方法方便。
  实现深拷贝,还有序列化等手段,比如实现 Serializable 接口,或者把对象转化成 JSON。
  所以,在现实情况下, 原型模式变成了一种思想,而不是加快对象创建速度的工具 。 小结
  本课时,我们主要看了几个与性能相关的设计模式,包括一些高频的考点。我们了解到了  Java 实现动态代理 的两种方式,以及他们的区别,在现版本的 JVM 中,性能差异并不大;我们还了解到 单例模式的三种创建方式 ,并看了一个 double check 的反例,平常编码中,推荐使用枚举去实现单例;最后,我们学习了 享元模式 和 原型模式 ,它们概念性更强一些,并没有固定的编码模式。
  我们还顺便学习了 arthas 使用 trace 命令,寻找耗时代码块的方法,最终将问题定位到 Spring 的 AOP 功能模块里,而这种场景在复杂项目中经常发生,需要你特别注意。
  此外,在设计模式中,对性能帮助最大的是生产者消费者模式,比如异步消息、reactor 模型等,而这一部分内容,我们将在之后的文章中进行讲解。

孩子也未必是自己的好我就是举着放大镜也找不着的好孩子这段日子得以完完整整地守在家里,也算一种机缘,刚好是小孩从走到跑,从不会说话到不会说人话的那个阶段,所见所闻,颇有些触动。所谓孩子就是哀乐中年的眼前23股主力资金净流入超亿元沪指9月21日下跌0。17,主力资金全天净流出40。95亿元。其中,创业板主力资金净流出18。23亿元,沪深300成份股主力资金净流出18。90亿元。申万所属的一级行业中,今日涨幅330亿资金借道ETF抄底多位明星经理获新弹药证券时报记者裴利瑞随着A股大幅回调,不少资金却越跌越买,借道基金布局市场的热情高涨。近一个月来,A股主流宽基指数悉数下跌,9月21日,上证指数盘中一度跌破3100点,上证50指数更租电脑帮助初创企业解决资金难题办公电脑租赁作为一种全新行业备受关注,之所以发展如此迅速,在于其出现高度符合了新形势下企业变革升级的需求,也得益于互联网和共享经济模式的快速发展。传统的租赁模式,非常麻烦先要找到门今年前8个月646。3亿元稳岗资金直达市场主体今年以来,人社部持续推动援企稳岗政策落实加力加效,通过稳市场主体稳就业。今年前8个月646。3亿元稳岗资金直达市场主体。数据显示,18月各地全面推广免申即享经办新模式,已向1120消防安全科普家庭实用防火安全知识一栋4层民房起火经过1个多小时的紧张扑救8名被困人员均被成功救出这是如何做到的呢?前不久的一个夜晚,湖南邵阳一4层民房起火。接到群众报警后,湖南邵阳县消防救援大队迅速出动赶赴现场救今评弹小伙985高校毕业4年后读专科弃屠龙技选济世方,是认清现实更是勇于追梦评论员邱延波小伙985高校毕业4年后读专科登上热搜。26岁的李先俊从重庆大学毕业4年后,重新高考,被湖北中医药高等专科学校中医学专业录取。他18岁考入重庆大学视觉传达专业,毕业后专女孩首次例假黄金年龄是几岁?为了孩子,建议家长提前知导语对于许多有女儿的家庭父母来说,往往在生活当中会遇到各种各样的烦恼,举例来说,随着女孩年龄的增长,到了青春期会遇到面临月经到来的问题,这也是广大家长特别关心的一个问题。女孩的第1孩子被欺负,家长别只会教孩子打回去,否则的话下场更惨孩子被欺负,家长别只会教孩子打回去否则的话下场更惨很多家长在面对孩子被欺负的情况下,都会让孩子打回去,但事实上,这种方式不仅解决不了问题,还有可能让孩子的处境变得更惨。前段时间,我生育力评估,是保鲜膜吗?在电影重庆森林里,有这样一句经典的独白秋刀鱼会过期,肉罐头会过期,连保鲜纸都会过期我开始怀疑,在这个世界上还有什么东西是不会过期的文艺的对白有无法言说的惆怅而现代女性没有时间悲伤因孩子每天睡多久合适?实用妙招拯救晚睡娃晚上睡不着,早上不想起,你家孩子的睡眠生物钟,让你着急了吗?今天,我们就来和家长们聊一聊孩子的睡眠问题。孩子究竟睡多长时间合适对于儿童的最佳睡眠时间一直以来都存在争议。每个儿童的睡
上海第一大企业换人,年营收达到9723亿元,超越了上汽集团据有关数据统计,刚毕业的大学生一般都会选择到北上广深这种一线城市工作。这些城市的工作机会比较多,并且也拥有许多大公司,晋升机制比较完善。而上海市的百强企业榜单,就是评价这些公司实力高密农商银行多项举措保障员工权益,凝聚发展内部合力大众网海报新闻记者邓楠通讯员李如意潍坊报道高密农商银行坚持以党建为统领,以保障职工权益为出发点,持续强化以员工为中心的管理理念,切实将关心关爱员工政策落实到实处,让员工舒心家人放心降低实体经济企业成本江西省南昌市完善口岸功能助推物流提质降本增效南昌市深入推进优化跨境贸易环境,南昌水运进口转关离港确认业务正式开通,南昌企业进口货物在沿海港口的中转时间将大幅缩短,通关便利化水平继续提升。一是口岸通道快速发展。持续推进中欧班列被曝拖欠员工工资国美回应,黄光裕夫妇今年已减持超50亿股股票国美系的危机尚未度过,又迎来一锤先是被列为被执行人,后又被曝出拖欠员工薪酬。对此,国美对媒体回应员工薪酬问题时称,企业转型进程受阻,现金流承压明显,本月对薪酬发放做了一些临时应急调2022年福建省民企100强发布三家企业营业收入超千亿元来源台海网在26日举行的省政府新闻发布会上,2022年福建省民营企业100强正式发布,这是省工商联第5年发布该榜单。今年福建民营企业100强企业营业收入入围门槛达43亿元,比上年增(新华全媒)小巨人为中国制造注入活力2022世界制造业大会上的专精特新企业观察新华社合肥9月22日电题小巨人为中国制造注入活力2022世界制造业大会上的专精特新企业观察新华社记者吴慧珺胡锐薄如蝉翼的高精度铜箔应用于新型显示产业的高端材料能检测物料成分的激光成三星GalaxyTabS8系列展现创新魅力,凸显卓越新体验随着时代的发展,越来越多的人都喜爱起了智能产品的大屏幕和轻薄便携性,也使得平板电脑成为了人们日常休闲娱乐的主要工具之一。同时,其还逐渐兼具起了高效工作的使用需求。近期三星推出的Ga有房车拖挂资质的蔚来ES7专为成功暖男打造,五大杀器秒杀特斯拉中秋挑战赛一,蔚来的ESEC两大系列内卷蔚来ES8ES6EC6几款车价格是30几到50几万元,除了ES8尺寸超过5米,其余尺寸都是中型车,关键是前脸都是套娃策略,尾灯更是,看起来长折叠屏有多香?不止三星华为加入,华硕17。3英寸笔记本已开启预约文凯尔资讯手机电子产业的技术进步一直很快,从智能手机发展到普及,仅仅用了几年的时间。而目前智能手机的新征程也非常明确了折叠屏是未来厂商发力的重点。三星华为同年发布自家折叠屏手机同台变小了,也变强了!今晚这款VR新品彻底刷屏了相信各位数码发烧友都记得,在2015年前后,科技圈出现了一阵空前的VR热潮。不过那时候的VR头显大多比较笨重,体验也各有问题。接着2017年以后,VR的热度逐渐降温,整个行业则进入贾跃亭重掌法拉第未来,公司走上正轨,下周能回国了不?最近贾跃亭和他的法拉第未来又有新消息了。9月27日,贾跃亭在微博发文拨乱反正重回正轨,这是FF(法拉第未来)又一个重大拐点。衷心感谢携手拯救了FF的所有投资人合伙人公司高管和员工们