什么是capturing lambda

2024-03-15 03:36
文章标签 lambda capturing

本文主要是介绍什么是capturing lambda,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

先说影响:

在循环里面使用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);
}

这篇关于什么是capturing lambda的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/810666

相关文章

C++11第三弹:lambda表达式 | 新的类功能 | 模板的可变参数

🌈个人主页: 南桥几晴秋 🌈C++专栏: 南桥谈C++ 🌈C语言专栏: C语言学习系列 🌈Linux学习专栏: 南桥谈Linux 🌈数据结构学习专栏: 数据结构杂谈 🌈数据库学习专栏: 南桥谈MySQL 🌈Qt学习专栏: 南桥谈Qt 🌈菜鸡代码练习: 练习随想记录 🌈git学习: 南桥谈Git 🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈�

06 C++Lambda表达式

lambda表达式的定义 没有显式模版形参的lambda表达式 [捕获] 前属性 (形参列表) 说明符 异常 后属性 尾随类型 约束 {函数体} 有显式模版形参的lambda表达式 [捕获] <模版形参> 模版约束 前属性 (形参列表) 说明符 异常 后属性 尾随类型 约束 {函数体} 含义 捕获:包含零个或者多个捕获符的逗号分隔列表 模板形参:用于泛型lambda提供个模板形参的名

如何掌握面向对象编程的四大特性、Lambda 表达式及 I/O 流:全面指南

这里写目录标题 OOP语言的四大特性lambda输入/输出流(I/O流) OOP语言的四大特性 面向对象编程(OOP)是一种编程范式,它通过使用“对象”来组织代码。OOP 的四大特性是封装、继承、多态和抽象。这些特性帮助程序员更好地管理复杂的代码,使程序更易于理解和维护。 类-》实体的抽象类型 实体(属性,行为) -》 ADT(abstract data type) 属性-》成

Java基础回顾系列-第三天-Lambda表达式

Java基础回顾系列-第三天-Lambda表达式 Lambda表达式方法引用引用静态方法引用实例化对象的方法引用特定类型的方法引用构造方法 内建函数式接口Function基础接口DoubleToIntFunction 类型转换接口Consumer消费型函数式接口Supplier供给型函数式接口Predicate断言型函数式接口 Stream API 该篇博文需重点了解:内建函数式

JavaSE(十三)——函数式编程(Lambda表达式、方法引用、Stream流)

函数式编程 函数式编程 是 Java 8 引入的一个重要特性,它允许开发者以函数作为一等公民(first-class citizens)的方式编程,即函数可以作为参数传递给其他函数,也可以作为返回值。 这极大地提高了代码的可读性、可维护性和复用性。函数式编程的核心概念包括高阶函数、Lambda 表达式、函数式接口、流(Streams)和 Optional 类等。 函数式编程的核心是Lambda

Kotlin高阶函数与Lambda表达式及内联函数的介绍

目录 1、高阶函数1.1、什么是高阶函数?1.1.1、不带返回值的高阶函数1.1.2、带参数且带返回值的高阶函数1.1.3、与一般的函数进行比较 1.2、如何使用?1.3、高阶函数有什么作用? 2、Lambda表达式2.1、什么是Lambda表达式?2.1.1、无参数的写法2.1.2、有参数的写法2.1.3、有参数且有返回值的写法 2.2、如何使用?2.3、Lambda表达式有什么作用? 3

C++11,可变参数模板,lambda表达式,包装器

可变参数模板 在C++11中模板也可以接收多个不定参数,就和int printf(const char *format, ...);函数一般模板也可以接收多个参数; // 可变参数模板template<class ...Args>void testArgs(Args... args){}int main(){testArgs(123, 'a', "abc",

C++:Lambda表达式及匿名函数

C++Lambda表达式及匿名函数 1. 语法2. 语法3. 变量捕获 1. 语法 [ 捕获列表 ] ( 参数列表 ) -> 返回类型 { 函数体 } [OuterVar](int x, int y) -> int{return OuterVar + x + y;} 可以忽略参数列表和返回类型,但必须永远包含捕获列表和函数体。 忽略参数列表等价于指定一个空函数列表,

lambda表达式用法——C#学习笔记

“Lambda 表达式”是一个匿名函数,它可以包含表达式和语句,并且可用于创建委托或表达式目录树类型。  实例如下: 代码如下: using System;using System.Collections.Generic;using System.IO;using System.Linq;using System.Security.Policy;using System.

Java基础-Lambda表达式的使用套路

1.列表循环 1.1.普通的forEach循环 goodsSkuBatch.stream().forEach(goodsSkuPromote -> {// 循环处理对象 TODO}); 2.列表过滤 // 去重复信息: 过滤收集后补数据库中的ID, 收集listList<EmailMessage> crudList = emailDataList.stream().collect