【问题标题】:If join blocks the main thread, why it doesn't block in loop?如果 join 阻塞了主线程,为什么它不会阻塞在循环中?
【发布时间】:2019-06-28 06:48:29
【问题描述】:

Thread 实例的 join() 方法可用于将线程执行的开始“连接”到另一个线程执行的结束,这样一个线程在另一个线程结束之前不会开始运行。如果在 Thread 实例上调用 join(),则当前正在运行的线程将阻塞,直到 Thread 实例执行完毕

但是如果我有多个线程并且当我在循环内调用 join 时。所有线程并行运行。但是根据加入概念,首先加入的线程应该完成,然后只有主线程应该允许加入其他线程。

public class MultiThreading implements Runnable {


private int name;
public MultiThreading(int number) {
    name =number;
}

@Override
public void run() {
    for (int i = 0; i <= 10; i++ ) {

           System.out.println("Thread number :" + name +" Printed value "+i);

        try {
            Thread.sleep(100);
        } catch (final InterruptedException e) {
            return;
        }
    }
}


public static void main(String[] args) throws InterruptedException {

    final Thread[] workers = new Thread[3];
    for (int i = 0; i < nthreads; ++i) {
        workers[i] = new Thread(new MultiThreading(i));
    }
    for (final Thread t : workers) {
        t.start();

    }

    for (final Thread t : workers) {
        t.join();
        System.out.println("Thread joind to main thread : " + t.getName());
    }
    System.out.println("Main thread ends");
}

}

在上面的代码中,如果第一个线程被加入,那么主线程应该被阻塞并且不应该让其他线程加入(直到加入的线程完成run方法的执行)。但是所有线程都是并行连接的。输出就像 -

Thread number :0 Printed value 0
Thread number :1 Printed value 0
Thread number :2 Printed value 0
Thread number :0 Printed value 1
Thread number :1 Printed value 1
Thread number :2 Printed value 1
Thread number :0 Printed value 2
Thread number :1 Printed value 2
Thread number :2 Printed value 2
Thread number :0 Printed value 3
Thread number :1 Printed value 3
Thread number :2 Printed value 3
Thread number :0 Printed value 4
Thread number :1 Printed value 4
Thread number :2 Printed value 4
Thread number :1 Printed value 5
Thread number :0 Printed value 5
Thread number :2 Printed value 5
Thread number :0 Printed value 6
Thread number :1 Printed value 6
Thread number :2 Printed value 6
Thread number :1 Printed value 7
Thread number :0 Printed value 7
Thread number :2 Printed value 7
Thread number :0 Printed value 8
Thread number :1 Printed value 8
Thread number :2 Printed value 8
Thread number :1 Printed value 9
Thread number :0 Printed value 9
Thread number :2 Printed value 9
Thread number :1 Printed value 10
Thread number :0 Printed value 10
Thread number :2 Printed value 10
Thread joind to main thread : Thread-0
Thread joind to main thread : Thread-1
Thread joind to main thread : Thread-2
Main thread ends

【问题讨论】:

  • 你有什么问题?
  • @GhostCat 我看到了程序的输出,我不明白 OP 在期待什么。
  • @MauricePerry 在加入循环中,如果第一个线程被加入,为什么主线程没有被阻塞。它甚至在第一个加入的线程完成之前就允许其他线程加入。
  • @AnshulKabra 主线程被阻塞,直到第一个线程结束。
  • @GhostCat 非常感谢您的快速澄清。我感到困惑的原因是线程正在做同样的事情。我让第二个线程运行了更长的时间。

标签: java multithreading java-threads


【解决方案1】:

首先:

Thread 实例的 join() 方法可用于将线程执行的开始“连接”到另一个线程执行的结束

这是一个误解:这与启动线程无关。 Join 只执行此操作:一个正在运行的线程将一直等到另一个线程结束。

当您执行someThread.join() 时,调用该方法的线程将等到 someThread 结束!

但是所有线程都是并行连接的。

是的,因为它们都完成了。

您的线程执行完全相同的操作,因此除了这里或那里的几纳秒(由于写入 System.out 无论如何都会有效地同步内容,这些时间大多无效)它们都需要相同的时间。

所以当你加入第一个线程时......其他两个线程将完成。所以第一次调用join() 使“主”线程等待第一个线程结束,随后的调用“立即”发生,因为这些线程也完成了。

为了延迟事情,将循环数作为MultiThreading 类的参数,然后确保您的线程需要不同的时间。如果 Thread-0 循环了 10 次,Thread-1 循环了 20 次,而 Thread-2 循环了 30 次,你会看到每个连接实际上都在等待相应的线程结束。

长话短说:您立即启动所有线程,因此它们立即开始并行运行。后面的 join 调用只是延迟 ma​​in 线程的进程,直到每个工作线程结束。

【讨论】:

  • IMO,您应该从此答案中删除“主线程”或“活动线程”的想法。他们只会混淆事物。在线程 t 终止之前,t.join() 调用不会返回。关于join(),还有什么新手需要知道的吗?
  • P.S.,我正在悄悄地从我们的词汇表中消除“当前线程”。当计算机只有一个 CPU 时,它意味着内核代码中的某些东西,用户模式代码的作者可以很容易地将其理解为“调用者”。但是,当系统有四个或十六个或六十多个 CPU 都在努力工作时,“当前线程”是什么意思?我认为我们可以通过说“调用者”或“调用线程”来为新手提供很多帮助。
猜你喜欢
  • 2021-10-19
  • 2020-01-02
  • 1970-01-01
  • 2019-02-18
  • 1970-01-01
  • 2016-06-26
  • 1970-01-01
  • 2021-11-12
  • 1970-01-01
相关资源
最近更新 更多