先说结论:

在循环里面使用lambda函数造成捕获性lambda后,会产生多余的引用,从而使程序进行原来本可以避免的垃圾回收。从效率的角度上看,这是我们应该避免的。

接下来我们看看什么是capturing lambda。

在学习Disruptor(高性能队列)的时候,它的官方文档有这样一段话:(重点部分已加粗)

ByteBuffer bb = ByteBuffer.allocate(8);
for (long l = 0; true; l++)
{bb.putLong(0, l);ringBuffer.publishEvent((event, sequence) -> event.set(bb.getLong(0)));Thread.sleep(1000);
}

This would create a capturing lambda, meaning that it would need to instantiate an object to hold the ByteBuffer bb variable as it passes the lambda through to the publishEvent() call. This will create additional (unnecessary) garbage, so the call that passes the argument through to the lambda should be preferred if low GC pressure is a requirement.

从上面的代码我们可以看到在一个lambda函数(event, sequence) -> event.set(bb.getLong(0)里引用到了外部变量bb。那么实际上在虚拟机翻译的时候,首先会在lambda所代表的内部类里生成一个引用,这个引用在内部类构造的时候引用了外面的变量bb(lambda表达式其实就是一个匿名内部类)。

类似于以下代码(我们屏蔽掉disrutor的细节):

        String bb;Functional a = new Functional() {private final String bb = InnerClass.this.bb;@Overridepublic void test() {System.out.printf(bb);}};

也就是说在内部类里我们多了一个bb的引用副本,那么在循环的时候,循环多少次就会多几个不必要的bb引用副本。这也是为什么disruptor文档说“This will create additional (unnecessary) garbage”,这会增加额外的不必要的垃圾。

那么怎么解决呢?

解决方式就是在lambda的外部类增加一个静态方法,类似于:

    public static void translate(LongEvent event, long sequence, ByteBuffer buffer){event.set(buffer.getLong(0));}public static void main(String[] args) throws Exception{ByteBuffer bb = ByteBuffer.allocate(8);for (long l = 0; true; l++){bb.putLong(0, l);ringBuffer.publishEvent(LongEventMain::translate, bb);Thread.sleep(1000);}}

和原来的对比一下,方便体会:

ByteBuffer bb = ByteBuffer.allocate(8);
for (long l = 0; true; l++)
{bb.putLong(0, l);ringBuffer.publishEvent((event, sequence) -> event.set(bb.getLong(0)));Thread.sleep(1000);
}

最后,关于内部类里生成外部类变量引用的事,可以看我的另一篇文章:假如面试官问你java内部类是如何处理外部引用的,你该怎么回答?

java造成capturing lambda后需要注意的事情相关推荐

  1. Java 8 - 03 Lambda 函数式接口Predicate Consumer Function Supplier

    文章目录 Pre Predicate 断言型函数式接口 Consumer 消费型函数式接口 Function 功能型函数式接口 Supplier 供给型函数式接口 小结 函数式接口如何处理异常信息 P ...

  2. Java forEach中 Lambda Expr中的 final变量要求

    https://my.oschina.net/wadelau/blog/1859419 Java forEach中 Lambda Expr中的 final变量要求 Java8闭包 闭包是一个函数在创建 ...

  3. comparator接口_8000字长文让你彻底了解 Java 8 的 Lambda、函数式接口、Stream 用法和原理

    我是风筝,公众号「古时的风筝」.一个兼具深度与广度的程序员鼓励师,一个本打算写诗却写起了代码的田园码农! 文章会收录在 JavaNewBee 中,更有 Java 后端知识图谱,从小白到大牛要走的路都在 ...

  4. Java 8 新增lambda表达式(-)

    2019独角兽企业重金招聘Python工程师标准>>> Java 8 刚于几周前发布,日期是2014年3月18日,这次开创性的发布在Java社区引发了不少讨论,并让大家感到激动.特性 ...

  5. Java stream 处理分组后[升降序key]取每组最大

    Java stream 处理分组后[升降序key]取每组最大 一. 需求 二. 整活 git仓库直达 如何让同事看不懂你写的代码 然后觉得你非常牛逼 这里用到了stream()与Lambda 需要有点 ...

  6. 【Java 8】Lambda表达式

    本文参考书籍<Java 8实战>,陆明刚.劳佳  译,如有侵权,请联系删除! 我们了解了利用行为参数化来传递代码有助于应对不断变化的需求,它允许我们定义一个代码块来表示一个行为,然后传递它 ...

  7. Java入门之Lambda表达式的应用

    Lambda表达式 JDK8开始支持Lambda表达式,用来让程序编写更优雅 利用Lambda可以更简洁的实现匿名内部类与函数声明与调用 基于Lambda提供stream流式处理极大简化对集合的操作 ...

  8. Java匿名内部类和Lambda表达式

    Java匿名内部类和Lambda表达式 一.Java匿名内部类 二.JavaLambda表达式 全部代码: 代码运行结果: 一.Java匿名内部类 我们在使用匿名内部类时,需要记住以下几个重要的知识点 ...

  9. Java箭头函数,lambda函数

    Java箭头函数,lambda函数 lambda表达式实质就是一种语法糖,(建议尽量不要使用lambda表达式,代码太简洁,难懂,难以调试) lambda表达式的简单例子: 不需要参数,返回5 ()- ...

  10. java se翻译_(翻译)Java SE 8 Lambda 标准库概览(下)

    Java SE 8 Lambda 标准库概览 8,Collectors 在目前的例子中,我们已经使用了collect()方法来收集流中的元素并放入List或Set中了.collec()方法的参数是一个 ...

最新文章

  1. debian,ubuntu下安装MariaDB,并设置密码,修改端口,允许外网访问
  2. 32位计算机能玩什么游戏,系统32位操作能玩什么游戏?
  3. Kafka消费者Consumer常用配置
  4. 关于代码运行时间Stopwatch的使用
  5. 自动化测试框架搭建-配置-1
  6. 学电脑从新手到高手_小白如何学手绘插画?新手到高手必学的四套教程【614期】...
  7. security工作笔记008---springBoot springCloud中的security配置全解
  8. opengles图像处理之边缘检测
  9. SPC X-R控制图的操作步骤
  10. 恩尼格玛模拟器_用C语言编的恩格尼码模拟器
  11. <Halcon> 区域划分算子partition_dynamic和partition_rectangle
  12. 【读论文】基于深度学习的铁路道岔转辙机故障诊断(3DESIGN)
  13. 用C语言建立一个顺序栈
  14. hbase bulkload java,HBase Bulkload 失败问题处理以及改进
  15. 通过php执行mysql语句进行学生成绩表的增删改查
  16. 论文研读 —— 7. Very Deep Convolutional Networks for Large-Scale Image Recognition (1/3)
  17. Java 面试题大全(整理版)1000+ 面试题附答案详解
  18. 人人车被曝近百员工聚集北京总部维权
  19. Far planner 代码系列(33) 关于real_world_contour和contour_graph
  20. 苹果账号申请流程——99刀(个人版或公司版 ),299刀(企业版)

热门文章

  1. java文字生成图片
  2. 使用MindSpore进行一阶导数计算
  3. SQL函数入门--统计函数+分组函数
  4. 惠普计算机工作站,HP 笔记本计算机和移动工作站电池安全召回和更换计划
  5. HTML+CSS基础学习笔记1
  6. 数据预处理--无量纲化
  7. 在两台电脑之间通过网线、局域网快速传东西的几种方法
  8. 【秋招内推】近期互联网公司秋招内推合集
  9. CheckPoint管理平台提示Certificate revoked
  10. MySQL高级篇——锁的概述与案例应用