简体   繁体   English

如何用Java解释此多线程程序的代码输出?

[英]How to explain the code output of this multi-threading program in Java?

I am studying multi-threading in java and wrote the following code. 我正在研究Java中的多线程并编写了以下代码。

    public class MulThread extends Thread
{
    public void run()
    {
        for(int i=1; i<5;i++)
        {
            try
            {
                Thread.sleep(500);
            }
            catch(Exception e){ System.out.println(e);}
            System.out.println(i);
        }
    }


public static void main(String [] args)
{
    MulThread t1 = new MulThread();
    MulThread t2 = new MulThread();
    MulThread t3 = new MulThread();

    t1.start();
    t1.run();
    t2.start();
    t2.run();

    t3.start();
    t3.run();

}
}

I discussed this with some friends, and I came to the conclusion that the output should be a complete mess. 我与一些朋友讨论了这一点,得出的结论是输出应该是完全混乱的。 But for some reason, the compiler always produces the following output: 但是由于某种原因,编译器始终会产生以下输出:

1
1
2
2
3
3
4
4
1
1
2
2
3
3
4
4
1
1
2
2
3
3
4
4

Can someone explain what exactly is happening here when the threads reach the scheduler? 有人可以解释当线程到达调度程序时这里到底发生了什么吗? Why isn't the output a mess of 1, 2, 3, and 4, each repeated 6 times in a random soup? 为什么输出的1、2、3和4乱七八糟,却在随机汤中重复了6次?

A few of my mentors tell me it's just a coincidence, and it depends on my OS or something, but I'm skeptical about that. 我的一些导师告诉我,这只是一个巧合,它取决于我的操作系统或某些东西,但是我对此持怀疑态度。 I've run the code over 10 times, and it always produces the same results. 我已经运行了10多次代码,并且始终会产生相同的结果。

This: 这个:

t1.start();

starts the thread as you would want. 根据需要启动线程。 The threading mechanism will call run() under the covers. 线程机制将在后台调用run()

But you then call this: 但是您可以这样称呼:

t1.run();

which calls the run() method directly and block your main thread whilst it runs (since you're simply calling a blocking method). 直接调用run()方法并在run()阻塞主线程(因为您只是在调用阻塞方法)。 You don't need this. 你不需要这个 Simply start() and your new thread will run as you expect (separate to your main thread). 只需start() ,您的新线程便会按预期运行(与主线程分离)。

Note that calling run() directly in these circumstances is often unusual and an indication of confusion! 请注意,在这种情况下直接调用run()通常是不常见的,并且会引起混乱!

It's useful to print the thread name in these circumstances ( via Thread.currentThread().getName() ) to see what's going on (and perhaps naming your threads too, via a different Thread constructor) 在这种情况下( via Thread.currentThread().getName() )打印线程名称很有用,以查看发生了什么(也许还可以通过不同的Thread构造函数来命名您的线程)

When you call t1.start() , a secondary thread starts and runs the run() method. 当您调用t1.start() ,辅助线程将启动并运行run()方法。 When you call t1.run() , you are executing the run() method on the main thread. 调用t1.run() ,您正在主线程上执行run()方法。

This means that t2.start(); 这意味着t2.start(); will only be executed after t1.run(); 仅在t1.run();之后执行t1.run(); finished the loop, and at this point the thread created by t1.start() has already finished. 完成了循环,此时t1.start()创建的线程已经完成。

Since the loop of the run() method contains a large sleep (half a second), there's a very high probability that the outputs of t1.start() (which runs on a secondary thread) and t1.run() (which runs on the main thread) will be interleaved (since that sleep is enough time for the second thread to get control and print the next output while the first thread is sleeping). 由于run()方法的循环包含大量睡眠(半秒),因此t1.start() (在辅助线程上运行)和t1.run() (运行t1.run()的输出很有可能主线程上的线程)将被交织(因为休眠是第二线程在第一个线程处于休眠状态时有足够的时间来获得控制权并打印下一个输出的时间)。

If you reduce the sleep period, you'll probably see different output. 如果减少睡眠时间,则可能会看到不同的输出。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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