1.Scala_基础
package com.ecust.demo
/**
* @author Jinxin Li
* @create 2021-01-11 15:25
*/
object SparkCore05_Closure_Scala {
//将函数作为返回值来使用
def main(args: Array[String]): Unit = {
def test() ={
def inner()={
}
println("xxxxxx")
//下划线表示将函数作为对象来使用
val f = inner _
f
}
//对上述方法调用
val f: () => Unit = test()
f()
test()()
def test1() ={
def inner()={
}
//下划线表示将函数作为对象来使用
inner _
}
//todo > 也可以直接指定类型 但是在企业中不这么用
def test2():()=>Unit ={
def inner()={
}
//下划线表示将函数作为对象来使用
inner
}
}
/*public User getUser(){
User user = new User();
return user;
}*/
}
2.闭包
package com.ecust.demo
/**
* @author Jinxin Li
* @create 2021-01-11 15:34
*/
object SparkCore06_Closure_Scala {
def main(args: Array[String]): Unit = {
//1.outer函数=>方法
//2.参数x编译后应该是方法的局部变量 局部变量有效范围是当前方法内部有效
//3.inner函数=>文件中方法
//4.inner方法执行时间点:在outer方法执行之后9
//5.outer方法如果执行完了会弹出栈,其中的局部变量会回收
//6.inner方法凭什么能用x 底层进行特殊操作,一个函数如果使用了外部的变量,需要将变量的生命周期改变
//7.函数将变量包含到函数的内部,形成一个闭合的效果,称之为闭包
//8.早期是使用匿名内部类实现的
def outer(x:Int)={
println("执行外部程序")
def inner(y:Int)={
println("执行内部程序")
x+y
}
inner _
}
val f: Int => Int = outer(20)
println(f)
val i: Int = f(20)
println(i)
// println(outer(20)(20))
}
}
3.Java模仿
package com.ecust.demo;
/**
* @author Jinxin Li
* @create 2021-01-11 15:49
*/
public class SparkCore08_Closure_Scala {
private static int x = 10;
public static void main(String[] args) {
SparkCore08_Closure_Scala obj = new SparkCore08_Closure_Scala();
//先执行方法outer,方法弹出栈
int outer = obj.outer(20);
//在执行方法inner
int inner = obj.inner(20);
// System.out.println(x);
System.out.println(inner);
}
//java方法中不能写方法
/*public void outer(int x){
public void inner(){
}
}*/
public int outer(int x){
return x;
}
public int inner(int y){
return x+y;
}
}
4.实战1
package com.ecust.demo
import org.apache.spark.rdd.RDD
import org.apache.spark.{SparkConf, SparkContext}
/**
* @author Jinxin Li
* @create 2021-01-11 16:19
*/
object SparkCore09_Closure_Spark {
def main(args: Array[String]): Unit = {
val conf: SparkConf = new SparkConf().setAppName("SparkCoreTest").setMaster("local[*]")
val sc: SparkContext = new SparkContext(conf)
val rdd: RDD[Int] = sc.makeRDD(List(1, 2, 3, 4))
val user = new user()
rdd.foreach(
num=>{
println("age:" + user.age+num)
}
)
sc.stop()
}
//这里可以选择是否进行序列化类
class user extends Serializable {
var age:Int= 30
}
}
5.实战2
package com.ecust.demo
import org.apache.spark.rdd.RDD
import org.apache.spark.{SparkConf, SparkContext}
/**
* @author Jinxin Li
* @create 2021-01-11 16:19
* 这种情况下还是不能运行,因为需要进行闭包检查,当executor内部引用了外部变量时,就会监测外部变量能否使用
*/
object SparkCore10_Closure_Spark {
def main(args: Array[String]): Unit = {
val conf: SparkConf = new SparkConf().setAppName("SparkCoreTest").setMaster("local[*]")
val sc: SparkContext = new SparkContext(conf)
val rdd: RDD[Int] = sc.makeRDD(List[Int]())
val user = new user()
rdd.foreach(
//todo 源码:ClosureCleaner.clean(f, checkSerializable)
num=>{
println("age:" + user.age+num)
}
)
sc.stop()
}
//这里可以选择是否进行序列化类
class user extends {
var age:Int= 30
}
}
6.总结
在spark的scala程序中,我们都是定义的main方法
main方法中又定了在executor的方法
executor在使用main方法中的变量时,要进行要将main方法变量提高生命周期,
版本之前以匿名内部类的方法实现,在调用之前检查能够进行序列化传输
并编译成高声明周期的变量
称为闭包检查