Подтвердить что ты не робот

Что означает этот поток, соединяющий код?

В этом коде, что означают два соединения и разрыв? 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();
   }
}
4b9b3361

Ответ 1

  Что означает этот код присоединения к потоку?

Цитировать из метода Thread.join() javadocs:

join() Ожидает смерти этой нити.

В вашем примере кода запущен поток, который, вероятно, является основным потоком.

  1. Основной поток создает и запускает потоки t1 и t2. Два потока начинают работать параллельно.
  2. Основной поток вызывает t1.join() для ожидания завершения потока t1.
  3. Поток t1 завершается, а метод t1.join() возвращается в основной поток. Обратите внимание, что t1 мог уже завершиться до того, как будет выполнен вызов join(), и в этом случае вызов join() будет немедленно возвращен.
  4. Основной поток вызывает t2.join() для ожидания завершения потока t2.
  5. Поток t2 завершается (или, возможно, завершился раньше, чем был выполнен поток t1), а метод t2.join() возвращается в основной поток.

Важно понимать, что потоки t1 и t2 работали параллельно, но основной поток, который их запустил, должен дождаться их завершения, прежде чем он сможет продолжить. Это общая закономерность. Кроме того, t1 и/или t2 могли завершиться до того, как основной поток вызовет для них join(). Если это так, то join() не будет ждать, но немедленно вернется.

t1.join() means cause t2 to stop until t1 terminates?

Нет. Основной поток, который вызывает t1.join(), прекратит работу и будет ждать завершения потока t1. Поток t2 работает параллельно и на него вообще не влияют вызов t1 или t1.join().

С точки зрения try/catch, join() выбрасывает InterruptedException, что означает, что основной поток, вызывающий join(), может сам быть прерван другим потоком.

while (true) {

Наличие соединений в цикле while - странный паттерн. Как правило, вы выполняете первое соединение, а затем второе соединение, соответственно обрабатывая InterruptedException в каждом случае. Не нужно их зацикливать.

Ответ 2

Это вопрос любимого 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. Независимо от того, кто начал поток t1 или t2 (в этом случае метод main), main будет ждать завершения t1 и t2 своей задачи.

Однако важно отметить, что t1 и t2 сами могут работать параллельно, независимо от последовательности вызовов соединения на t1 и t2. Это поток main/daemon, который должен ждать.

Ответ 3

join() означает ожидание завершения потока. Это метод блокировки. Ваш основной поток (тот, который выполняет join()) будет ждать строки t1.join(), пока t1 не завершит свою работу, а затем сделает то же самое для t2.join().

Ответ 4

Одна картинка стоит тысячи слов.

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

Надеемся на полезные, более подробно нажмите здесь

Ответ 5

Когда поток tA вызывает tB.join(), его причины не только ожидают, что tB будет умирать, либо tA будет прервано, а создаст связь между последним оператором в tB и следующей операцией после tB.join() в потоке tA.

Все действия в потоке происходят до того, как какой-либо другой поток успешно возвращается из соединения() в этом потоке.

Это означает, что программа

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 Memory Model не требует "переноса" нового значения "sharedVar" из threadB в основной поток без отношения heppens-before (начало потока, объединение потоков, использование "синхронизированного" ключевого слова, использование переменных AtomicXXX и т.д.).

Ответ 6

Из документации оракула страница по Присоединения

Метод join позволяет одному потоку ждать завершения другого.

Если t1 является объектом Thread, поток которого в настоящее время выполняется,

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

Если t2 - объект Thread, поток которого в настоящее время выполняется,

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

join API - это низкоуровневый API, который был введен в более ранних версиях java. Множество вещей было изменено с течением времени (особенно с выпуском jdk 1.5) на передней панели concurrency.

Вы можете достичь того же с помощью API java.util.concurrent. Вот некоторые примеры:

Обратитесь к связанным вопросам SE:

дождитесь, пока все потоки закончат работу в java

Ответ 7

Проще говоря:
t1.join() возвращается после завершения t1.
Он ничего не делает для потока t1, кроме как дождаться его завершения.
Естественно, код, следующий за t1.join() будет выполняться только после t1.join().

Ответ 8

Для меня поведение Join() всегда сбивало с толку, потому что я пытался вспомнить, кто кого будет ждать. Не пытайтесь запомнить это таким образом.

Внизу это чистый механизм wait() и notify().

Все мы знаем, что когда мы вызываем wait() для любого объекта (t1), вызывающий объект (main) отправляется в комнату ожидания (состояние Blocked).

Здесь основной поток вызывает join(), который wait() под прикрытием. Таким образом, основной поток будет ждать, пока не получит уведомление. Уведомление дается t1, когда он заканчивает свою работу (завершение потока).

После получения уведомления главный выходит из комнаты ожидания и приступает к его исполнению.

Ответ 9

Надеюсь, поможет!

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
}

Ответ 10

скажем, наш основной поток запускает потоки t1 и t2. Теперь, когда вызывается t1.join(), основной поток приостанавливает себя до тех пор, пока поток t1 не умирает, а затем возобновляет себя. Точно так же, когда t2.join() выполняется, основной поток снова приостанавливает себя, пока поток t2 не умирает, а затем возобновляет работу.

Итак, вот как это работает.

Кроме того, цикл while здесь не нужен.