What is java thread join

Метод Thread.join() в Java

В этом руководстве мы обсудим различные методы join() в классе Thread . Мы подробно рассмотрим эти методы и некоторый пример кода.

Подобно методам wait() и notify() , join() является еще одним механизмом синхронизации между потоками.

Вы можете быстро просмотреть этот учебник , чтобы узнать больше о wait() и notify() .

2. Метод Thread.join () ​

Метод соединения определен в классе Thread :

 > `public final void join() throws InterruptedException` 

Ожидает завершения этого потока.

Когда мы вызываем метод join() для потока, вызывающий поток переходит в состояние ожидания. Он остается в состоянии ожидания до тех пор, пока указанный поток не завершится.

Мы можем увидеть это поведение в следующем коде:

 class SampleThread extends Thread    public int processingCount = 0;    SampleThread(int processingCount)    this.processingCount = processingCount;   LOGGER.info("Thread Created");   >    @Override   public void run()    LOGGER.info("Thread " + this.getName() + " started");   while (processingCount > 0)    try    Thread.sleep(1000);   > catch (InterruptedException e)    LOGGER.info("Thread " + this.getName() + " interrupted");   >   processingCount--;   >   LOGGER.info("Thread " + this.getName() + " exiting");   >   >    @Test   public void givenStartedThread_whenJoinCalled_waitsTillCompletion()   throws InterruptedException    Thread t2 = new SampleThread(1);   t2.start();   LOGGER.info("Invoking join");   t2.join();   LOGGER.info("Returned from join");   assertFalse(t2.isAlive());   > 

При выполнении кода следует ожидать результатов, подобных приведенным ниже:

INFO: Thread Created INFO: Invoking join INFO: Thread Thread-1 started INFO: Thread Thread-1 exiting INFO: Returned from join 

Метод join() также может возвращать значение, если указанный поток был прерван . В этом случае метод выдает InterruptedException .

Наконец, если указанный поток уже завершен или не был запущен, вызов метода join() немедленно возвращает значение .

 Thread t1 = new SampleThread(0);  t1.join(); //returns immediately 

3. Методы Thread.join() с тайм-аутом​

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

Есть две временные версии , которые перегружают метод join() :

«public final void join(long millis ) throws InterruptedException Ожидает

самое большее миллисекунды миллисекунды, пока этот поток не умрет. Тайм-аут, равный 0, означает ожидание вечности».

«public final void join(long millis,int ` nanos ) выдает InterruptedException Ожидает`

самое большее миллисекунды плюс наносекунды , пока этот поток не умрет».

Мы можем использовать timed join() , как показано ниже:

 @Test   public void givenStartedThread_whenTimedJoinCalled_waitsUntilTimedout()   throws InterruptedException    Thread t3 = new SampleThread(10);   t3.start();   t3.join(1000);   assertTrue(t3.isAlive());   > 

В этом случае вызывающий поток ожидает завершения потока t3 примерно 1 секунду. Если поток t3 не завершится в этот период времени, метод join() возвращает управление вызывающему методу.

Timed join() зависит от времени ОС. Таким образом, мы не можем предполагать, что join() будет ждать ровно столько времени, сколько указано.

4. Методы Thread.join() и синхронизация​

В дополнение к ожиданию завершения вызов метода join() имеет эффект синхронизации. join() создает отношение « происходит до »:

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

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

Следовательно, несмотря на то, что вызов метода join() для потока, находящегося в прекращенном состоянии, возвращается немедленно, в некоторых ситуациях нам все равно нужно вызывать его.

Мы можем увидеть пример неправильно синхронизированного кода ниже:

 SampleThread t4 = new SampleThread(10);  t4.start();   // not guaranteed to stop even if t4 finishes.   do     > while (t4.processingCount > 0); 

Чтобы правильно синхронизировать приведенный выше код, мы можем добавить timed t4.join() внутри цикла или использовать какой-либо другой механизм синхронизации.

5. Вывод​

Метод join() весьма полезен для синхронизации между потоками. В этой статье мы обсудили методы join() и их поведение. Мы также рассмотрели код, использующий метод join() .

Как всегда, полный исходный код можно найти на GitHub .

Источник

Guide to Join Threads in Java

In this tutorial, we will learn how to join two Threads and why there is a need to join Threads in java. We will explore in detail the Thread.join() API and the different versions of the same along with practical examples.

We will also see how we can end up in a deadlock situation while using join() and the ways to use it effectively in our code.

1. Introduction to Thread Joining

A Thread is a lightweight process that allows a program to operate more efficiently by running multiple threads in parallel. If we have a requirement where the first Thread must wait until the second Thread completes its execution then we should join these 2 Threads.

Let’s take an example to understand it more clearly. Suppose we have 3 Threads performing 3 different kinds of activities for a marriage application.

  • The wedding cards distribution activity starts once the wedding cards printing activity completes and the wedding cards printing activity starts once we fix the venue for the wedding.
  • We can say that in this case, Thread-3 has to wait until Thread-2 completes and also Thread-2 has to wait until Thread-1 completes its execution.
  • Thread-2 has to call Thread-1.join(), and Thread-3 has to call Thread-2.join()so that they will wait until the completion of the other thread.

The join() method makes a calling Thread enters into waiting for the state until the Thread on which join() is called completes its execution.

  • A Thread ‘t1’ wants to wait until another Thread ‘t2’ completes its execution then t1 has to call the join() method on t2,
  • t2.join() called by t1.
  • When t1 executes t2.join() then t1 enters into waiting state immediately and continues to wait until t2 completes its execution and terminates.
  • Once t2 completes then only t1 continues its execution again.

thread join

2.1 Joining without Timeout

The default join() method makes the current Thread wait indefinitely until the Thread on which it is called is completed. If the Thread is interrupted then it will throw InterruptedException.

public final void join() throws InterruptedException

Let’s now look at an example of how to use join() method.

public class ChildThread extends Thread < public void run() < for(int i=1; icatch(Exception e) < System.out.println(e); >System.out.println(“child thread execution - ” + i); > > >
ChildThread th1 = new ChildThread(); // Starting child Thread th1.start(); // main thread joining the child thread th1.join(); // main Thread printing statements System.out.println(“main thread completed”);

Notice the program output. The main thread is calling join() method on child thread and waiting for its completion so after calling join(). So, all the statements from the child thread print before the main thread statements.

child thread execution - 1 child thread execution - 2 child thread execution - 3 child thread execution – 4 main thread completed
  • join(long millis): It makes the current Thread wait until the Thread on which it is called is completed or the time specified in milliseconds has expired.
  • join(long millis, int nanos): It makes the current Thread wait until the Thread on which it is called is completed or the time specified in milliseconds + nanoseconds has expired.
public final synchronized void join(long millis) throws InterruptedException public final synchronized void join(long millis, int nanos) throws InterruptedException

Let’s now look at how it works with an example.

// Creating child Thread Object ChildThread th1 = new ChildThread(); // Starting child Thread th1.start(); //main thread joining the child thread with 1000ms expiration time th1.join(1000); // main Thread printing statements System.out.println(“main thread completed”);

When the program executes, the main thread will wait at max 1000ms and will be invoked anytime after that.

child thread execution - 1 main thread completed child thread execution - 2 child thread execution - 3 child thread execution - 4

3. Interrupting a Joined Thread

A waiting Thread can be interrupted by another Thread using the interrupt() method. Once the waiting Thread is interrupted, it immediately comes out of the waiting state and moves into Ready/Runnable state and waits for the Thread Scheduler to allocate the processor to begin the execution again.

public class ThreadJoiningInterrupt < public static void main(String[] args) < ChildThread childThread = new ChildThread(Thread.currentThread()); childThread.start(); try < childThread.join(); //Joined >catch (InterruptedException ie) < System.out.println("main Thread is interrupted"); >for (int i = 1; i > > class ChildThread extends Thread < private static Thread parentThreadRef; public ChildThread(Thread parentThreadRef) < this.parentThreadRef = parentThreadRef; >public void run() < parentThreadRef.interrupt(); //Interrupted for (int i = 1; i > >

Notice the program output, once the child thread interrupts the joined main thread then both thread executes simultaneously.

Child Thread Execution - 1 main Thread is interrupted Child Thread Execution - 2 main Thread Execution - 1 main Thread Execution - 2 main Thread Execution - 3 main Thread Execution - 4 Child Thread Execution - 3 Child Thread Execution – 4

4. Watch out for Deadlocks

We must be careful while using join() method as sometimes it may lead to a deadlock situation. If two Threads call the join() method on each other then both threads enter into waiting for state and wait for each other forever.

Similarly, if a thread, by mistake, joins itself then it will be blocked forever, and JVM must be shutdown to recover.

In this tutorial, we have learned the need to join two threads and how to use Thread.join() API with or without the expiration duration. We have also seen how we can interrupt a joined Thread. We also learned avoiding deadlock situations while using join() .

Источник

Читайте также:  Only child css selector
Оцените статью