Java-8中的线程循环

3

我创建了这段代码:

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

但这不是正确的,它会打印一个随机整数,有时甚至会打印出不合逻辑的数字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?为什么它没有按照顺序打印出 1、2、3……等数字?请解释一下。

11
为什么不合逻辑?这个循环在 i == 5 时运行并将其增加到 6。只有当你使用 <= 时,它才会从循环中跳出。主线程在循环中非常快,新创建的线程只能看到 i 作为 6,而没有在循环内休眠主线程。 - jlordo
1
你正在运行代码时打印的是 i 的值,而不是循环迭代时的值的副本。 - Peter Lawrey
1
“实际上6不存在吗?” 如果 i == 6 不存在,你的循环就不会停止。 - Peter Lawrey
1
当你看到这个时,你会认为它会打印出来: 我肯定不会。你只有一个变量,每次只能有一个值。 - biziclop
我只是想在循环中测试线程 @Holger 只是好奇而已 - Youcef LAIDANI
显示剩余6条评论
3个回答

6

Thread执行Runnable的run方法时,循环可能已经完成执行,并且最后一个值i取的是6,请记住你正在执行i<=5,这意味着当循环结束时,i将等于6


2
你得到的是完全符合逻辑的输出结果,你可能会得到更奇怪的打印输出。正如 Thread 中的 start 方法的 javadoc 所说:

结果是两个线程正在同时运行:当前线程(从调用 start 方法返回)和另一个线程(执行其 run 方法)。

在循环中启动的 子线程 的执行时间是不确定的,你得到的结果显示,在最后一个循环完成之前,1 个线程执行了,而在整个循环完成后,4 个线程执行了。
你在循环中加入Thread.sleep(2000);后,得到你期望的顺序只是因为你让每个子线程有足够的执行时间,这就是全部。从本质上/理论上讲,执行顺序是不确定的。

-1

如果像其他语言一样,您的线程代码以非确定性方式进行调度,因此在运行线程代码时将访问变量i的实际值。

我重写了一些更清晰的代码:

public class Main {

static 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”设置为静态的。

更清晰的解决方案是使用一个继承自Thread的类,并在构造函数中设置它的“i”,这样子类的每个线程实例都将拥有自己的值。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接