1. 说明
闭包可以理解为 当发生函数嵌套时,内层函数中使用到了外出函数的变量,此时内层函数和外层函数所处的环境就是闭包(它会延长外层函数的声明周期)
内层函数可以使用外层函数的变量
但是,外层函数是获取不到内层函数的变量的
可以看我之前写的例子: 传送门
scala中的闭包:
内层函数和外层函数所处的环境,是同一台机器中的JVM中
spark中的闭包:
我们经常通过算子传递Lambda表达式,如果Lambda表达式中用到了Driver端的变量
那么他们会被序列化后,分发的不同的计算节点中去
但是各个节点对Driver端变量的修改,Driver端是感应不到的
2. scala中的闭包
test("scala中的闭包") {
// TODO 对数组中的元素求和
// 设置累加变量
var s = 0
var arr = Array(1, 2, 3, 4, 5)
arr.foreach(s += _)
println(s"结果: $s") // 结果: 15
}
3. spark中的闭包
test("spark中的闭包") {
// 初始化 spark配置实例
val sparkconf: SparkConf = new SparkConf().setMaster("local[4]").setAppName("")
// 初始化 spark环境对象
val sc: SparkContext = new SparkContext(sparkconf)
// 设置累加变量
var s = 10
val arrRDD = sc.parallelize(Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10),5)
// 查看每个分区的内容
arrRDD.mapPartitionsWithIndex(
(i, iter) => {
println(s"分区编号$i :${iter.mkString(" ")}");
iter
}
).collect()
/*
* TODO 过程说明
* 1.foreach算子中的Lambda表达式使用到了 Driver端的变量i
* 2.通过 foreach算子 中 sc.clean(f) 对Lambda表达式做序列化检查
* 主要是检查 Lambda表达式中用到的变量实例 是否可以序列化
* 如果不支持序列化 将报错
* 3.在 各个分区节点上 反序列化获取变量实例,对分区内数据做累加
* 4.各分区累加的结果,Driver端获取不到
*
* */
arrRDD.foreach(
i => {
println(s"$s : $i")
s += i
}
)
println(s"s变量结果:$s")
sc.stop()
}