UFO少年アブドラジャン:
私は変更をしようとすると、ラムダとローカル変数を取得します。私が使用する必要があります知って効果的に最終ラムダのローカル変数のために。私は失敗した変更ローカル変数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();
}
出力異なるたびに:
- -------- --------仕事の後に
97 - -------- --------作業後
99
私は配列にこの作業罰金をアトミックに変更します。
public void a(GlobalL globalL) {
Integer[] number = {1};
Work work = () -> {
number[0]++;
return number[0];
};
globalL.setWork(work);
}
出力毎回:
-------- --------仕事の後
102
- 何がアレイと、原子このような状況で起こっているの?
- 非最終ローカル変数で匿名クラスとlabmdaを仕事にする方法?
- どのJVMは、ラムダで動作しますか?
オイゲンCovaci:
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)IMO、それは別の問題でなければなりません。いくつかの言葉でそれを置くために、ラムダは単なるシンタックスシュガーであり、彼らは匿名内部クラスにコンパイルされます。
why array works correctly?
質問、答えは:それはしていません。同じ理由++アトミック演算子ではない だけ、のは、1000年と言うようにするスレッドの数を増やし、それを証明するには:
for (int i = 0; i < 1000; i++) {
new Thread(() -> {
globalL.printSum();
}).start();
}
私は取得しています:
-------- --------仕事の後972