我创建了这段代码:
static int i;
public static void main(String[] args) throws InterruptedException {
for (i = 1; i <= 5; i++) {
new Thread(() -> {
hello(i);
}).start();
}
}
public static void hello(int i) {
System.out.println("Thread number = " + i);
}当你看这个的时候,你认为它会打印出来:
Thread number = 1
Thread number = 2
Thread number = 3
Thread number = 4
Thread number = 5但是这是不正确的,它打印一个随机的int,它打印的不合逻辑的6有时会这样:
Thread number = 5
Thread number = 6
Thread number = 6
Thread number = 6
Thread number = 6我在以下之后添加Thread.sleep(2000);:
for (i = 1; i <= 5; i++) {
new Thread(() -> {
hello(i);
}).start();
Thread.sleep(2000);
}它告诉我一个正确的结果:
Thread number = 1
Thread number = 2
Thread number = 3
Thread number = 4
Thread number = 5为什么它给我显示了第一个结果,它给我显示了6个,而实际上,6是不存在的?为什么不打印订购的int 1,2,3,.?有什么解释吗?
发布于 2017-03-05 11:15:25
当Thread执行Runnable's run方法时,循环可能已经完成了它的执行,而最后一个i得到的值是6,记住您正在执行i<=5,这意味着当循环finish的i将等于6时。
发布于 2017-03-05 11:45:33
您得到的是完全的逻辑输出,您可能会得到更多奇怪的打印输出。正如Thread所说:
结果是两个线程同时运行:当前线程(从对start方法的调用返回)和另一个线程(执行其run方法)。
sub Thread在循环中启动的时间是不确定的,您得到的结果显示,在循环线程完成其最后一个循环之前执行了1个线程,在整个循环完成之后执行了4个线程。
在循环中添加Thread.sleep(2000);后获得预期顺序的原因仅仅是给每个sub Thread足够的时间在实际操作中执行,仅此而已。执行顺序在本质上/理论上是不确定的.
发布于 2017-03-05 11:46:10
如果与其他语言一样,线程代码是以非确定性方式调度的,那么在运行线程代码时,将访问以实际值表示的var i。
我重写了一些更简洁的代码:
公共类Main {
静态int i=0;
public static void main(String[] args) throws Exception
{
// Lambda Runnable
Runnable task = () -> {
hello(i);
};
for (i = 1; i <= 5; i++) {
new Thread(task).start();
}}
public static void hello(int i) {
System.out.println("Thread number = " + i);
}}
注:我必须将"i“设置为”静态“。
Cleaner的解决方案是使用线程派生的类及其"i“,并在构造函数中设置它,因此子类的每个线程实例都有自己的值。
https://stackoverflow.com/questions/42607607
复制相似问题