此线程连接代码是什么意思?


156

在这段代码中,两个join和break是什么意思?t1.join()导致t2停止直到t1终止?

Thread t1 = new Thread(new EventThread("e1"));
t1.start();
Thread t2 = new Thread(new EventThread("e2"));
t2.start();
while (true) {
   try {
      t1.join();
      t2.join();
      break;
   } catch (InterruptedException e) {
      e.printStackTrace();
   }
}


3
由于它将阻塞并等待线程终止,因此为什么要使用while循环?
Mehdi

我想@MahdiElMasaoudi即使线程被中断也要继续等待吗?可能不是这样做的好方法
forresthopkinsa

如果有帮助,请记住在这里接受答案。
灰色的

如前所述,您无需while(true)调用join方法。
Chaklader Asfak Arefe

Answers:


311

此线程连接代码是什么意思?

引用Thread.join()方法javadocs

join() 等待该线程死亡。

运行示例代码的线程可能是主线程

  1. 主线程创建并启动t1t2线程。这两个线程开始并行运行。
  2. 主线程调用t1.join()以等待t1线程完成。
  3. t1线程完成和t1.join()在主线程方法返回。请注意,t1在进行join()呼叫之前可能已经完成,在这种情况下,join()呼叫将立即返回。
  4. 主线程调用t2.join()以等待t2线程完成。
  5. t2线程完成(或者它可能已经完成了前t1线程所做的那样)以及t2.join()在主线程方法返回。

重要的是要了解t1t2线程已经并行运行但是启动它们的主线程需要等待它们完成才能继续。这是常见的模式。同样,t1和/或t2可能在主线程调用它们之前完成join()。如果是这样,则join()不会等待,但会立即返回。

t1.join() 意味着导致t2停止直到t1终止?

否。正在调用的线程t1.join()将停止运行并等待t1线程完成。该t2线程并行运行并且不受t1t1.join()在所有通话。

就try / catch而言,join()引发InterruptedException意味着正在调用的主线程join()本身可能会被另一个线程中断。

while (true) {

使联接处于while循环状态是一种奇怪的模式。通常,InterruptedException在每种情况下,您都将先进行第一次联接,然后进行第二次联接,以适当地处理。无需将它们放在一个循环中。


24
+1这是一个非常奇怪的模式,可能可以删除。
m0skit0 2013年

3
如果t1首先完成,则t2完成。这似乎是一个顺序过程。一个线程首先完成,然后另一个。多线程的意义何在?
user697911 2013年

9
因为t1t2可以并行运行。只是main需要他们俩先完成才可以继续。这是@ user697911的典型模式。
2013年

3
while之所以存在该循环,是因为(我想)join()如果有人中断,它想重试这些呼叫?我当然不会这样写@ user697911。
2013年

5
循环在那里确保两者t1t2完成。就是 如果t1抛出异常InterruptedException,它将循环返回并等待t2。一种替代方法是在每个线程的Try-Catch中等待两个线程,这样就可以避免循环。另外,根据EventThread,以这种方式执行操作很有意义,因为我们正在运行2个线程,而不是一个。
Michael Bisbjerg 2013年

68

这是一个最喜欢的Java面试问题。

Thread t1 = new Thread(new EventThread("e1"));
t1.start();
Thread e2 = new Thread(new EventThread("e2"));
t2.start();

while (true) {
    try {
        t1.join(); // 1
        t2.join(); // 2  These lines (1,2) are in in public static void main
        break;
    }
}

t1.join()意思是,t1表示类似“ 我想先完成 ”。的情况也是如此t2。无论是谁启动t1t2线程启动(在这种情况下为main方法),main都会等到t1t2完成他们的任务。

然而,重要的一点要注意了,t1并且t2自己可以并行运行,而不管连接调用顺序t1t2。它是main/daemon必须等待的线程。


3
好的例子。关于“可以并行运行”:那又如何呢?重要的是主线程将首先等待t1,然后等待t2。t1或t2在做什么(从主线程的角度来看)真的没关系
Alex

1
您提到了“主/守护程序”线程。我了解的主要内容,但守护程序与此无关。主线程是非守护程序。
灰色

1
t1.join(); t2.join();在两个线程都终止之前,将不允许执行连接的线程继续。在其他地方没有非常不寻常的代码的情况下,联接的顺序无关紧要。
David Schwartz

那么,仅在t1完成时才会调用t2.join()吗?
Leo Droidcoder

换句话说,如果我们要“序列化” t1和t2线程的执行,则需要将t1.join()紧接在t1.start()之后,因为主线程开始了t1(然后是t2),并且当然将其从中删除了。试着抓。显然,这样做将导致并行性的损失。
dobrivoje

47

join()表示等待线程完成。这是一种阻止方法。您的主线程(执行该操作的线程join())将在该t1.join()行上等待,直到t1完成其工作,然后对执行相同的操作t2.join()


29

一张图片胜过千言万语。

    Main thread-->----->--->-->--block##########continue--->---->
                 \                 |               |
sub thread start()\                | join()        |
                   \               |               |
                    ---sub thread----->--->--->--finish    

希望对您有用,更多详细信息请点击这里


3
清晰准确。
dobrivoje

10

当线程tA调用tB.join()时,它不仅导致tB死亡或tA本身被中断,而且导致tB中的最后一个语句与tA线程中tB.join()之后的下一个语句之间发生先于关系。

线程中的所有操作都会发生-在任何其他线程从该线程上的join()成功返回之前。

这意味着程序

class App {
    // shared, not synchronized variable = bad practice
    static int sharedVar = 0;
    public static void main(String[] args) throws Exception {
        Thread threadB = new Thread(() -> {sharedVar = 1;});
        threadB.start();
        threadB.join();

        while (true) 
            System.out.print(sharedVar);
    }
}

一律列印

>> 1111111111111111111111111 ...

但是程序

class App {
    // shared, not synchronized variable = bad practice
    static int sharedVar = 0;
    public static void main(String[] args) throws Exception {
        Thread threadB = new Thread(() -> {sharedVar = 1;});
        threadB.start();
        // threadB.join();  COMMENT JOIN

        while (true)
            System.out.print(sharedVar);
    }
}

不仅可以打印

>> 0000000000 ... 000000111111111111111111111111 ...

>> 00000000000000000000000000000000000000000000 ... 

始终只有0。

因为Java内存模型不需要在没有heppens-before关系的情况下(线程启动,线程连接,使用'synchonized'关键字,使用AtomicXXX变量等),无需将'sharedVar'的新值从threadB转移到主线程。


5

简而言之:完成
t1.join()后返回t1
它不执行任何线程操作t1,只是等待它完成。
自然,t1.join()仅在t1.join()返回后才执行 代码跟随 。


1
仅在t1.join()返回+1
mohsen.nour

3

联接上的 oracle文档页面

join方法允许一个线程等待另一线程的完成。

如果t1是Thread当前正在执行其线程的对象,

t1.join() : causes the current thread to pause execution until t1's thread terminates.

如果t2是Thread当前正在执行其线程的对象,

t2.join(); causes the current thread to pause execution until t2's thread terminates.

joinAPI是低级API,已在Java的早期版本中引入。在一段时间内(尤其是在JDK 1.5版本中),并发前端已经做了很多更改。

您可以使用java.util.concurrent API实现相同的目的。一些例子是

  1. 在上使用invokeAllExecutorService
  2. 使用 CountDownLatch
  3. 使用ForkJoinPoolnewWorkStealingPoolExecutors(由于Java 8)

请参阅相关的SE问题:

等到所有线程在Java中完成工作


1

对我来说,Join()的行为总是令人困惑,因为我试图记住谁将等待谁。不要试图那样记住它。

下面是纯的wait()和notify()机制。

我们都知道,当我们在任何对象(t1)上调用wait()时,调用对象(主)都会发送到等候室(处于阻塞状态)。

在这里,主线程正在调用join(),它是幕后的wait()。因此主线程将等待,直到通知它为止。t1完成运行(线程完成)时会发出通知。

收到通知后,main从等候室出来并继续执行。


0

希望能帮助到你!

package join;

public class ThreadJoinApp {

    Thread th = new Thread("Thread 1") {
        public void run() {
            System.out.println("Current thread execution - " + Thread.currentThread().getName());
            for (int i = 0; i < 10; i++) {
                System.out.println("Current thread execution - " + Thread.currentThread().getName() + " at index - " + i);
            }
        }
    };

    Thread th2 = new Thread("Thread 2") {
        public void run() {
            System.out.println("Current thread execution - " + Thread.currentThread().getName());

            //Thread 2 waits until the thread 1 successfully completes.
            try {
            th.join();
            } catch( InterruptedException ex) {
                System.out.println("Exception has been caught");
            }

            for (int i = 0; i < 10; i++) {
                System.out.println("Current thread execution - " + Thread.currentThread().getName() + " at index - " + i);
            }
        }
    };

    public static void main(String[] args) {
        ThreadJoinApp threadJoinApp = new ThreadJoinApp();
        threadJoinApp.th.start();
        threadJoinApp.th2.start();
    }

    //Happy coding -- Parthasarathy S
}

-3

假设我们的主线程启动了线程t1和t2。现在,当调用t1.join()时,主线程将自行挂起,直到线程t1死掉,然后继续自身。类似地,当执行t2.join()时,主线程会再次暂停自身,直到线程t2死掉然后继续。

因此,这就是它的工作方式。

另外,这里并不需要while循环。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.