在匿名线程中使用最终变量
Using final variables in anonymous threads
做这样的事情安全吗
for (int i = 0; i < 10; i++){
final int finalI = i;
new Thread(() -> {
// use finalI in the thread somehow
});
}
那么我想问的问题是,是否保证线程0..9看到finalI分别为0..9?
例如,如果在第二次迭代中更改了 finalI,并且第一个线程看到 finalI 为 1 而不是 0,会怎样。
我有 99% 的感觉这是不可能的,但我不知道匿名 class 是如何存储变量的,所以我不是 100% 确定。
如果 anon class 引用该变量的外部引用,那将是错误的,但它不是真正的引用,因为它是一个原语。那么线程 anon [=23 到底是怎么做的呢? =] 存储变量?
在幕后,JVM 是否让它在匿名线程中给出一个字段 private final int finalI,然后在构造函数中隐式设置它?
最后我会分别看到0..9
要了解内部发生的事情,让我们看看将变量声明为
final
会。
让我们拿
public class ThreadTest {
public static void main(String[] args) {
for(int i =0; i< 9; i++) {
final int finalI = i;
new Thread(()->{
try {
Thread.sleep(1000); // assuming a delay for some operations
System.out.println(Thread.currentThread().getName()+" "+finalI);
//System.out.println(Thread.currentThread().getName()+" "+ i); // can't do this.
} catch (Exception e) {
e.printStackTrace();
}
}).start();
}
}
}
方法的局部变量保存在栈中,一旦方法结束就会丢失。而 final variables/objects 即使在方法结束后也可以访问本地声明,因为它们被其他 classes/methods 引用,在这种情况下它是可运行的。
所以当我们执行
final int finalI = i;
我们正在创建一个新的 finalI 变量,它既不能改变之前的变量,也不能改变之前的线程使用这个值,因为之前的 finalI 是单独放在 JVM 堆中的。
做这样的事情安全吗
for (int i = 0; i < 10; i++){
final int finalI = i;
new Thread(() -> {
// use finalI in the thread somehow
});
}
那么我想问的问题是,是否保证线程0..9看到finalI分别为0..9?
例如,如果在第二次迭代中更改了 finalI,并且第一个线程看到 finalI 为 1 而不是 0,会怎样。
我有 99% 的感觉这是不可能的,但我不知道匿名 class 是如何存储变量的,所以我不是 100% 确定。
如果 anon class 引用该变量的外部引用,那将是错误的,但它不是真正的引用,因为它是一个原语。那么线程 anon [=23 到底是怎么做的呢? =] 存储变量?
在幕后,JVM 是否让它在匿名线程中给出一个字段 private final int finalI,然后在构造函数中隐式设置它?
最后我会分别看到0..9
要了解内部发生的事情,让我们看看将变量声明为
final
会。
让我们拿
public class ThreadTest {
public static void main(String[] args) {
for(int i =0; i< 9; i++) {
final int finalI = i;
new Thread(()->{
try {
Thread.sleep(1000); // assuming a delay for some operations
System.out.println(Thread.currentThread().getName()+" "+finalI);
//System.out.println(Thread.currentThread().getName()+" "+ i); // can't do this.
} catch (Exception e) {
e.printStackTrace();
}
}).start();
}
}
}
方法的局部变量保存在栈中,一旦方法结束就会丢失。而 final variables/objects 即使在方法结束后也可以访问本地声明,因为它们被其他 classes/methods 引用,在这种情况下它是可运行的。
所以当我们执行
final int finalI = i;
我们正在创建一个新的 finalI 变量,它既不能改变之前的变量,也不能改变之前的线程使用这个值,因为之前的 finalI 是单独放在 JVM 堆中的。