Lambda表达式的线程安全问题与闭包

Lambda表达式所使用的外部变量不能是可变的局部变量 (也就是说它只能接受成员变量,final的局部变量和参数)

下面例子中的test就是一个外部变量

实际上就是说,它不能接受非final的保存在线程祯中的变量, 等等, 这句话看起来是不是有点眼熟, 为什么会有这样的限制呢

首先这个Lambda表达式是运行在一个独立的子线程中,当这个线程运行时,它实际上拿到的是一个原始变量的副本(一个拷贝)

类似于经典的swap(a,b)函数,我相信每一个在大学学过c语言的人都碰到过这个考试题 😛

还记得Java8推出之前的热点问题么, java是否需要引入闭包, 那么Lambda表达式是否符合闭包的含义呢

闭包本身是一个函数,一段代码,一个可以被执行的逻辑, 它可以随意访问自身外部的其他变量,

Java8的Lambda表达式和匿名类也可以做类似于闭包的事情,比如下面这个例子里的Lambda表达式就访问了一个外部变量test

一般情况下很多人接触闭包都是通过javascript, javascript的闭包实际上是通过子函数来实现的,因为在javascript中只有一个函数的子函数才能访问这个函数的局部变量

f1方法中有一个局部变量 var n = 999 , f1的子方法f2是有权限访问这个变量n的

这里result就是一个闭包函数

  function f1(){

    var n=999;

    nAdd=function(){n+=1}

    function f2(){
      alert(n);
    }

    return f2;

  }

  var result=f1();

  result(); // 999

  nAdd();

  result(); // 1000

回过头来,我们可以说Lambda表达式是对值封闭,而不是对变量封闭的,局部变量被保存在线程帧上,如果这个局部变量是可变的,就可能引起线程不安全的问题