我尝试用lambda改变并获得局部变量。我知道,对于lambda中的局部变量,我应该有效地使用final。使用AtomicReference局部变量时,更改失败:
public class Lamb {
public static void main(String[] args) throws InterruptedException {
Lamb lamb = new Lamb();
GlobalL globalL = new GlobalL();
lamb.a(globalL);
for (int i = 0; i < 100; i++) {
new Thread(() -> {
globalL.printSum();
}).start();
}
Thread.sleep(3000);
System.out.println("--------After Work--------");
globalL.printSum();
}
public void a(GlobalL globalL) {
AtomicReference<Integer> number = new AtomicReference<>(0);
Work work = () -> {
number.getAndSet(number.get() + 1);
return number.get();
};
globalL.setWork(work);
}
}
class GlobalL {
private Work work;
public void printSum() {
System.out.println(work.getAndInc());
}
public void setWork(Work work) {
this.work = work;
}
}
interface Work {
int getAndInc();
}每次输出不同:
public void a(GlobalL globalL) {
Integer[] number = {1};
Work work = () -> {
number[0]++;
return number[0];
};
globalL.setWork(work);
}每次产出:
102
发布于 2020-02-26 07:22:49
1)守则:
number.getAndSet(number.get() + 1);
return number.get();是一个关键部分,因为有几个操作不是原子执行的。这就是你得到不同结果的原因。为了消除关键部分:
public void a(GlobalL globalL) {
AtomicInteger number = new AtomicInteger(0);
Work work = () -> {
return number.incrementAndGet();
};
globalL.setWork(work);
}2)你不能(见这或关于匿名课程的官方教程)
3)海事组织,这应该是一个单独的问题。简单地说,lambdas只是语法糖,它们被编译成匿名的内部类。
至于why array works correctly?的问题,答案是:it并不是出于同样的原因:为了证明它,只需将线程数增加到1000个:
for (int i = 0; i < 1000; i++) {
new Thread(() -> {
globalL.printSum();
}).start();
}我得到了:
https://stackoverflow.com/questions/60408193
复制相似问题