简体   繁体   中英

Java-8 Thread in Loop

I create this piece of code :

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);
}

When you look at this you think it will print :

Thread number = 1
Thread number = 2
Thread number = 3
Thread number = 4
Thread number = 5

But this is not correct it print a random int and the illogical it print 6 sometimes like :

Thread number = 5
Thread number = 6
Thread number = 6
Thread number = 6
Thread number = 6

I add Thread.sleep(2000); after :

for (i = 1; i <= 5; i++) {
    new Thread(() -> {
        hello(i);
    }).start();
    Thread.sleep(2000);
}

And it show me a correct result:

Thread number = 1
Thread number = 2
Thread number = 3
Thread number = 4
Thread number = 5

Why it show me that result in the first one and it show me 6, and in fact the 6 is not exist? and why it not print ordered int 1,2,3,...? Any explanation about that?

Thread执行Runnable's run方法时,循环可能已经完成其执行,并且i最后一次取值为6 ,请记住您正在执行i<=5 ,这意味着循环完成时i将等于6

What you got is completely logic output, and you might get even more odd print outputs. As the javadoc of the start method in Thread says:

The result is that two threads are running concurrently: the current thread (which returns from the call to the start method) and the other thread (which executes its run method).

The time when sub Thread started in the loop will execute is non-determinist, the result you got shows that 1 Thread executed before the loop thread finishing its last loop and 4 others executed after the entire loop finished.

The reason you got the order you expected after adding Thread.sleep(2000); in the loop is only because you give each sub Thread enough time to execute in real practice, that's all. The execution order is non-determinist essentially/theoretically.

if as in other language, Your thread code is scheduled in a non-determinist way, so at time of running the threading code will access the var i taking ACTUAL value.

I rewrote a bit cleaner code:

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);
}

}

note I have to set "i" to static..

A Cleaner solution will be to use a Thread-derived class with its "i" and set it in constructor, so every thread instance of subclass will have its own value..

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM