Nes*_*oli 17 java lambda java-8
我知道出于并发原因,我无法在Java 8中更新lambda中局部变量的值.所以这是非法的:
double d = 0;
orders.forEach( (o) -> {
d+= o.getTotal();
});
Run Code Online (Sandbox Code Playgroud)
但是,如何更新实例变量或更改本地对象的状态?例如,Swing应用程序我有一个按钮和一个声明为实例变量的标签,当我点击按钮时我想要隐藏标签
jButton1.addActionListener(( e) -> {
jLabel.setVisible(false);
});
Run Code Online (Sandbox Code Playgroud)
我没有编译器错误并且工作正常,但是...改变lambda中对象的状态是正确的吗?我将来会遇到并发问题还是坏事?
这是另一个例子.想象一下,下面的代码是在一个servlet的方法doGet中我会在这里遇到一些问题吗?如果答案是肯定的:为什么?
String key = request.getParameter("key");
Map<String, String> resultMap = new HashMap<>();
Map<String, String> map = new HashMap<>();
//Load map
map.forEach((k, v) -> {
if (k.equals(key)) {
resultMap.put(k, v);
}
});
response.getWriter().print(resultMap);
Run Code Online (Sandbox Code Playgroud)
我想知道的是:什么时候改变lambda中对象实例的状态是正确的?
ski*_*iwi 15
你的假设是不正确的.
你只能在lambdas中有效地改变最终变量,因为lambdas是匿名内部类的语法糖*.
*它们实际上不仅仅是语法糖,但这与此无关.
在匿名内部类中,您只能有效地更改最终变量,因此对于lambdas也是如此.
只要编译器允许,就可以使用lambdas做任何你想做的事情,现在就进入行为部分:
一些例子:
class MutableNonSafeInt {
private int i = 0;
public void increase() {
i++;
}
public int get() {
return i;
}
}
Run Code Online (Sandbox Code Playgroud)
MutableNonSafeInt integer = new MutableNonSafeInt();
IntStream.range(0, 1000000)
.forEach(i -> integer.increase());
System.out.println(integer.get());
Run Code Online (Sandbox Code Playgroud)
无论发生什么情况,这将按预期打印1000000,即使它取决于之前的状态.
现在让我们并行化流:
MutableNonSafeInt integer = new MutableNonSafeInt();
IntStream.range(0, 1000000)
.parallel()
.forEach(i -> integer.increase());
System.out.println(integer.get());
Run Code Online (Sandbox Code Playgroud)
现在它打印不同的整数,如199205或249165,因为其他线程并不总是看到不同线程所做的更改,因为没有同步.
但是说,我们现在摆脱了伪类和使用AtomicInteger,这是线程安全的,我们得到如下:
AtomicInteger integer = new AtomicInteger(0);
IntStream.range(0, 1000000)
.parallel()
.forEach(i -> integer.getAndIncrement());
System.out.println(integer.get());
Run Code Online (Sandbox Code Playgroud)
现在它再次正确打印1000000.
然而,同步成本很高,而且我们几乎失去了并行化的所有好处.
一般来说:是的,您可能会遇到并发问题,但只会遇到已经存在的并发问题.Lambdafying它不会使代码非线程安全在以前,或反之亦然.在您给出的示例中,您的代码(可能)是线程安全的,因为ActionListener只在事件调度线程上调用它.如果您已观察到Swing单线程规则,则不会访问任何其他线程jLabel,如果是,则不会对其进行线程干扰.但这个问题与使用lambdas是正交的.