public class Main {
static int i = 0;
public static void main(String[] args) {
for (; i < 2; i++)
new Thread(() -> System.out.println(i)).start();
}
}
我希望上面的代码打印出来
0
1
或
1
0
但令我惊讶的是我得到了
2
2
答案 0 :(得分:4)
当你在类i
的主体中引用Main
时,你真正在做的是引用静态变量Main.i
(编译器是礼貌的,不会让你输入完整路径。)在这种情况下,lambda没有捕获任何东西;可以从静态上下文中评估Main.i
。因此,如果lambda被解除了方法
public static void lambda$23() {
System.out.println(Main.i);
}
现在应该更清楚的是,你有多个线程竞相访问共享(mutable!)变量Main.i
;主线程正在更新它,并且创建的线程正在读取它。而且由于新线程中的读取很复杂,因此无法保证打印出来的内容。
答案 1 :(得分:2)
我运行相同的程序,它也为我提供了相同的结果。但如果你像那样运行它
for (; i < 2; i++) {
Thread.sleep(10);
new Thread(() -> System.out.println(i)).start();
}
结果成了
1
2
如果您在Thread.sleep(10)
输出
new Thread(() -> System.out.println(i)).start();
0
1
因为当前线程(main)在线程之前执行循环。
线程1和线程2在代码的第2步和第7步之间开始。操作系统处理线程调度,因此您无法在此程序中获得结果。
答案 2 :(得分:1)
结果因调度程序而异。无法预测它总是2,2
。见下图。您最终也可能获得不同的值。这是因为OS有自己的处理线程的方式。您可以阅读有关线程here 的更多信息--------------------------------- -------------------------------------------------- ------------------------------------------------- { {3}}图像显示了日食输出。