【问题标题】:Is there any order for Java main thread and user created thread execution?Java主线程和用户创建的线程执行有什么顺序吗?
【发布时间】:2018-06-29 10:22:12
【问题描述】:
public class SimpleThreads {
    // Display a message, preceded by the name of the current thread
    static void threadMessage(String message) {
        String threadName = Thread.currentThread().getName();
        System.out.format("%s: %s%n", threadName, message);
    }

    private static class MessageLoop implements Runnable {
        public void run() {
            String importantInfo[] = { "Mares eat oats", "Does eat oats","Little lambs eat ivy", "A kid will eat ivy too" };
            try {
                for (int i = 0; i < importantInfo.length; i++) {
                    threadMessage(importantInfo[i]);
                }
            } catch (Exception  e) {
                threadMessage("I wasn't done!");
            }
        }
    }

    public static void main(String args[]) throws InterruptedException {
        threadMessage("Starting MessageLoop thread");
        Thread t = new Thread(new MessageLoop());
        t.start();
        threadMessage("Waiting for MessageLoop thread to finish");
    }
}

输出

main: Starting MessageLoop thread
main: Waiting for MessageLoop thread to finish
Thread-0: Mares eat oats
Thread-0: Does eat oats
Thread-0: Little lambs eat ivy
Thread-0: A kid will eat ivy too

这里首先主线程打印了消息'main: Starting MessageLoop thread'。之后我启动了 Thread-0 OR MessageLoop 线程。

Thread t = new Thread(new MessageLoop());
t.start();

但在开始/打印 Thread-0 消息之前,它的打印“主”线程消息“main:等待 MessageLoop 线程完成”,并且仅在此之后执行 Thread-0。为什么?

【问题讨论】:

  • Thread t = new Thread(new MessageLoop()); t.start();(在main开始)应该如何在main之前开始?这里有什么令人惊讶的部分?
  • main 无论如何都会首先被调用
  • 因为启动线程不是瞬时的,所以启动线程是有开销的。与线程通过其启动开销并到达其threadMessage() 调用相比,主线程只需更快地 到达第二个threadMessage() 调用。这是一个简单的速度问题。这是一个竞态条件,但主线程通常会赢得比赛,因为它在start()threadMessage() 之间没有任何关系。
  • 如果没有显式同步,则无法保证这些语句(在不同线程中)的打印顺序。这意味着甚至不确定来自main 线程的waiting 消息是否总是首先打印。使用此代码的唯一保证是来自main 线程的所有消息都按顺序打印,并且来自Thread-0 的所有消息都按顺序打印。
  • 感谢大家的宝贵回复。

标签: java multithreading main


【解决方案1】:

这种行为是正常的,必须预料到,尽管你不能指望它。

您似乎希望main 线程等待第二个线程运行。但是,您的代码并非如此。 启动第二个线程的重点是并发执行,这意味着您不能仅仅因为代码中的语句是顺序的,就指望执行顺序。

如果你想让主线程wait让另一个线程执行,那么你需要同步它们。 然而,这违背了在您的情况下启动第二个线程的目的。如果您希望主线程等待第二个线程,您可以直接调用该方法而不启动第二个线程。

谷歌搜索“java并发”导致this one等页面。该文档解释了很多这些概念。

【讨论】:

    【解决方案2】:

    因为在线程上调用start() 不会使线程现在有效地执行。
    这是多线程的工作方式。

    来自Thread.start() 文档:

    使该线程开始执行; Java 虚拟机调用 该线程的运行方法。

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

    main 线程当前在您调用 t.start(); 时执行。
    线程将被 JVM 暂停,但您不掌握何时。

    在您的具体情况下,您将获得可重现的行为。
    t.start(); 之后,您可以快速执行一条语句:

     threadMessage("Waiting for MessageLoop thread to finish");
    

    它永远不会让主线程暂停并让新线程有效运行。

    t.start(); 之后添加一些需要更多时间在主线程中执行的语句或在其上调用sleep(),您应该会看到不同的行为。

    【讨论】:

    • 这如何解释为什么主线程总是先打印? IE。 Waiting 在打印第一条线程消息之前打印。
    猜你喜欢
    • 2016-07-24
    • 2017-08-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多