当前位置: 首页 > 面试题库 >

join()在Java中如何工作?是否保证在main()之前执行?

巴博耘
2023-03-14
问题内容

我正在尝试了解join()的代码流。

public class Multi extends Thread {

    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println(Thread.currentThread().getName());
        }
    }

    public static void main(String[] args) {

        Thread t1 = new Multi();
        Thread t2 = new Multi();
        Thread t3 = new Multi();
        Thread t4 = new Multi();

        t1.start();
        try {
            t1.join();
        } catch (Exception e) {
        }

        t2.start();        
        t3.start();
        try {
            t3.join();
        } catch (Exception e) {
        }        
        t4.start();

        System.out.println("........" + Thread.currentThread().getName());

        t1.setName("A");
        t2.setName("B");
        t3.setName("C");
        t4.setName("D");
    }
}

正如我在多次运行程序后所观察到的那样,输出始终是thread t1首先执行的,并且它将complete it's execution在任何时候都不会进行任何上下文切换t3 will start it will completes it's execution。我的理解清楚吗?

我观察到一些东西,如果不使用连接,main()将在线程执行的任何地方执行,这意味着我........main在程序的输出之间看到输出,但是join()总是在线程t3
之后执行。我怀疑这是语法main()开始之前的问题join(),因此它不应该跟随t3 / t1线程完成吗?这有意义还是我想念的东西?


问题答案:

简短答案

如何join()在Java 中工作?

我承认您的javadocjoin()有点不清楚,因为this当您初次阅读它时,谁指的并不明显。

这意味着线程调用将t.join()阻塞直到线程t完成执行为止。如果t当前线程调用时已经完成t.join(),那么当前线程不会停止并且只会继续运行。thisdoc中的单词指的是t这里,而不是调用该方法的线程。

它能保证执行之前main()吗?

[…]如果不使用main()联接,则在任何地方执行线程执行[…]

您不应该main()整体考虑。的一部分main()在其他线程之前执行,部分在并行执行,然后在其他线程执行。这实际上是什么start()join()控制。让我在下面解释。

你身上发生了什么 main()

以下是有关t1.start()和的事件顺序t1.join()。您显然可以以同样的方式思考t3

  1. 执行main()前面的指令t1.start()

  2. t1.start()启动线程t1t1.run()可能不会立即启动。)

  3. main()之间的指令t1.start()t1.join()中的指令并行执行(*)t1.run()
    注意:示例中没有任何内容,因此此时仅执行t1.run()指令。

  4. t1.join()

    • 如果t1.run()已经完成,则什么也不会发生并main()继续进行
    • 如果t1.run()尚未完成, 则主线程停止并等待 直到t1.run()完成。然后t1.run()完成,然后main()继续。
    • 的指令main()t1.join()执行

在这里您可以看到:

  • 保证main()前面的部分t1.start()在执行 之前 t1.run()
  • 的部分main()以下t1.join()是保证被执行 之后 t1.run()

(*)参见以下有关并行性的部分

我的意思是 “并行执行”

假设您在两个线程A和B中执行了这两组指令:

// Thread A                   |     // Thread B
                              | 
System.out.println("A1");     |     System.out.println("B1");
System.out.println("A2");     |     System.out.println("B2");
System.out.println("A3");     |     System.out.println("B3");

如果这两个线程是“并行执行的”,则意味着三件事:

  • 保证线程A的指令执行顺序:
    A1将在A2之前执行,而A2将在A3之前执行。

  • 保证线程B指令的执行顺序:
    B1将在B2之前执行,而B2在B3之前执行。

  • 但是,A和B的指令可以交织,这意味着以下所有可能(甚至更多):

A1,B1,A2,B2,B3,A3

B1,B2,A1,B3,A2,A3

A1,A2,A3,B1,B2,B3 //特殊情况下,A都在B之前执行

B1,B2,B3,A1,A2,A3 //特殊情况,其中B都在A之前执行

注意: 本节将并行性视为由操作系统创建的一种错觉,以使用户感觉事情在同时运行,实际上,只有一个核心按顺序执行指令,从一个html" target="_blank">进程/线程跳转到另一个。

实际上,一条A指令和一条B指令可以在2个独立的内核上同时执行(真正的并行性)。
无论如何,上面的3个要点仍然存在。正如@jameslarge所指出的,通常我们会使用一系列事件来对并发进行建模,即使对于多核也是如此。这忽略了两个事件同时发生的概念,它不会带来任何有用的东西,但会带来并发症。



 类似资料:
  • 问题内容: 我是Java新手,我想知道我是否具有以下典型的Java代码 JVM是否保证将始终运行finally块?为了了解我的来历,我已经习惯了C / C ++程序,如果您取消引用NULL指针,并且之后没有任何代码可以运行,它们可能会崩溃。 但是,据我了解Java和整个GC /托管内存业务的一般情况,没有诸如空指针取消引用之类的东西,所有这些都是可捕获的期望,因此,我的程序实际上没有崩溃的方法可能

  • 我想我错过了一些关于之前和之前的方式。我有一个规范文件,加载数据从夹具在之前的方法。这些数据中的一部分被用在之前的函数中,然后又被用在之前的函数中,以及在实际的测试中。规范文件包含2个测试。第一个测试按预期执行。第二个失败,因为beForeeach表示来自夹具的值之一未定义。 我的期望是,如果我加载数据从一个夹具在之前的方法,它应该是可用于所有测试规范文件。 在执行“检查按钮栏的状态”时,测试be

  • javax。servlet。Filter对象既可以用于身份验证(在需要完成任何servlet工作之前,过滤器需要捕获请求),也可以用于XSLT转换(servlet需要完全生成内容)。什么时候执行? 我知道这取决于实现(取决于web容器),但这似乎是所有人都需要解决的问题。 也许在web容器的每个过滤器注册的地方都设置了一个配置选项? 其他: 此外,什么控制过滤器的执行顺序?为什么FooFilter

  • 我是新来的春靴AOP。 用@Before注释的AOP方法是否在java验证注释(例如@NotNull)之前运行? 我还需要为每个请求运行一些其他自定义验证,但我需要在java验证注释运行之后运行这些验证。 哪个先跑? 我的控制器: 我的建议是:

  • 在katalon studio中为我的测试用例添加了一个新的自定义关键字,我正在创建隐式等待,上面的代码使我能够接收一条NoTouchElement异常消息,但我不知道隐式等待中规定的时间是否完全有效。有人能帮我弄清楚吗?非常感谢你!

  • 我经常把文本输出到文件中。我想知道:是如何工作的? 当我调用时,它是否在文件上写入文本?如果它不写文本,我需要使用flush函数来写数据吗? 例如: 如果while循环中发生错误,文件将在不写入数据的情况下关闭。如果我在while循环中使用函数,那么为什么要使用?如果我错了,请纠正我。