join()如何在java中工作?它是否保证在main()之前执行? [英] How does join() work in java? Does it guarantee the execution before main()?

查看:150
本文介绍了join()如何在java中工作?它是否保证在main()之前执行?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图用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();
线程t2 = new Multi();
线程t3 = new Multi();
线程t4 = new Multi();

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

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

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

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

输出总是,正如我在运行程序后观察到的很多时候,线程t1 首先执行,它将完成它的执行,无需任何上下文切换,并且每当 t3将启动它将完成它的执行。我的理解是否清楚?



我观察到一些事情,如果没有使用连接, main()在任何地方执行b / w执行线程,意味着我在程序的输出之间看到 ........ main 输出,但在之后()它总是在线程t3之后执行。这是我的疑问,因为 main() join()语法之前启动,所以它不应该遵循t3 / t1线程完成?它是否有意义或我缺少什么?

解决方案

简短回答



< blockquote>

如何 join()在java中工作?


我授予你 join() 的javadoc有点不清楚,因为不明显谁这个指的是当你第一次阅读它时。



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


它是否保证在 main()之前执行?



[...]如果没有使用连接, main()执行任何地方执行线程[... ]


您不应该将 main()视为一个整体。部分 main()在其他线程之前执行,其中部分并行,之后部分执行。这实际上是 start() join()控制。让我解释一下。



你的 main()


$ b会发生什么$ b

以下是关于 t1.start() t1.join()的事件序列。对于 t3 ,您显然可以采用相同的方式。


  1. 说明执行<$ p $ c> t1.start()之前的 main()执行


  2. t1.start()启动主题 t1 t1。 run()可能无法立即开始。)


  3. main() t1.start() t1.join()之间并行执行(*) t1.run()中的那些。

    注意:你的例子中没有,所以只有t1.run()指令是此时执行。


  4. t1.join()




    • 如果 t1.run()已经完成,没有任何反应并且 main()继续前进

    • 如果 t1.run()尚未完成,主线程停止并等待直到 t1.run()结束。然后 t1.run()结束,然后 main()恢复。


  5. t1.join()之后 main()的说明被执行


在这里你可以看到:




  • t1.start()之前的 main()部分保证在之前执行 t1.run()

  • main()以下 t1.join()保证在 t1之后执行 .run()



(*)见下面关于并行性的部分



我的意思是并行执行



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

  //线程A | //线程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);

如果这2个线程并行执行,这意味着3件事:




  • 保证线程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的执行之前执行的







注意:此部分将并行性视为幻觉由操作系统创建,使用户感觉事物同时运行,实际上只有一个核心执行指令顺序执行,从一个进程/线程跳转到另一个进程/线程。



实际上,A指令和B指令可以在2个独立的内核上同时执行(实际并行)。无论如何,上面的3个要点仍然有效。正如@jameslarge所指出的,通常我们使用一系列事件来建模并发性,即使对于多核也是如此。这就抛开了2个事件的同时性概念,这并没有带来任何有用的东西,而是带来了复杂性。


I am trying to understand the code flow with 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");
    }
}

The output is always, as i observe after running program many times, that thread t1 executes first and it will complete it's execution without any context switching, and whenever t3 will start it will completes it's execution. Is my understanding clear?

I observe something that, if no join is used, main() executes anywhere b/w the execution of threads, means i see ........main output in between the outputs of my program, but after join() it executes always after thread t3. Here is my doubt as main() starts before the join() syntax, so it should not follow the t3/t1 thread completion? Does it make sense or something I am missing?

解决方案

Short answer

How does join() work in java?

I grant you that the javadoc for join() is a little bit unclear, because it's not obvious who this refers to when you first read it.

It means that the thread calling t.join() blocks until the thread t has finished its execution. If t has already finished when the current thread calls t.join(), then the current thread does not stop and just keeps going. The word this in the doc refers to t here, not to the thread that calls the method.

Does it guarantee the execution before main()?

[...] if no join is used, main() executes anywhere b/w the execution of threads [...]

You shouldn't consider main() as a whole. Parts of main() are executed before the other threads, parts of it in parallel, and parts of it after. That's actually what start() and join() control. Let me explain below.

What happens in your main()

Here is the sequence of events regarding t1.start() and t1.join(). You can obviously think the same way for t3.

  1. The instructions of main() preceding t1.start() are executed

  2. t1.start() starts the thread t1 (t1.run() might not start right away.)

  3. The instructions of main() between t1.start() and t1.join() are executed in parallel(*) of the ones in t1.run().
    Note: You have none in your example, so only t1.run() instructions are executed at this moment.

  4. t1.join():

    • if t1.run() has already finished, nothing happens and main() keeps going
    • if t1.run() has not finished yet, the main thread stops and waits until t1.run() finishes. Then t1.run() finishes, and then main() resumes.
  5. The instructions of main() after t1.join() are executed

Here you can see that:

  • the part of main() preceding t1.start() is guaranteed to be executed before t1.run()
  • the part of main() following t1.join() is guaranteed to be executed after t1.run()

(*) see below section about parallelism

What I mean by "executed in parallel"

Suppose you have these 2 sets of instructions being executed in 2 threads A and 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");

If these 2 threads are "executed in parallel", this means 3 things:

  • the order of execution of the instructions of thread A is guaranteed:
    A1 will execute before A2, and A2 before A3.

  • the order of execution of the instructions of thread B is guaranteed:
    B1 will execute before B2, and B2 before B3.

  • however, A's and B's instructions can be interlaced, which means all of the following are possible (and more):

A1, B1, A2, B2, B3, A3

B1, B2, A1, B3, A2, A3

A1, A2, A3, B1, B2, B3 // special case where A's are all executed before B's

B1, B2, B3, A1, A2, A3 // special case where B's are all executed before A's


Note: this section dealt with parallelism as an illusion created by the OS to make the user feel like things run at the same time, where actually there is only one core executing instructions sequentially, jumping from one process/thread to another.

In fact, an A instruction and a B instruction could be executed simultaneously (real parallelism) on 2 separate cores. The 3 bullet points above still stand anyway. As @jameslarge pointed out, usually we model concurrency with a sequence of events, even for multicores. This leaves aside the concept of simultaneity of 2 events, which does not bring anything useful but complications.

这篇关于join()如何在java中工作?它是否保证在main()之前执行?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆