Java. Threads of execution. Methods of Thread class

Threads of execution. Methods of Thread class: join(), isAlive(), getPriority(), setPriority(). Examples

It is recommended that you familiarize yourself with the following topics before exploring this topic:


Contents


Search other websites:




1. Why is it necessary for the main (calling) thread to finish first? Explanation. Method join(). General form

Let two threads be given:

  • main (caller). A child thread is started (called) from the main thread;
  • child (called).

In order to get the result (object, data) from the child thread, the main (calling) thread must end last. If the main thread completes faster than the child thread, then most likely zero (initial) or intermediate values will be received from the child thread, which is error.

In order for the main thread to end last in the Java language, the join() method is used. The general form of the method is as follows:

public final void join() throws InterruptedException

here

  • InterruptedException – the class of the exception that is thrown when some other thread has interrupted the current thread. After this exception is thrown, the interrupted status of the current thread is reset.

 

2. Method join(). Example

Task. Implement a call to a child thread from the main thread. The maximum value of an array of integers is determined in the child thread. The result (maximum value) should be returned to the main thread and displayed.

Solution. A separate class is developed to create a child thread. In our case, the class is named Thread1. All necessary elements are declared in this class:

  • thr reference to a child thread of type Thread;
  • AI array of integers;
  • the variable maximum, which is the result of the thread;
  • constructor. The constructor performs the initial initialization of the array, as well as the creation and launch of the child thread. The thread is started by the start() method. If the constructor does not implement the creation and launch of a child thread, then the methods of the class instance will be executed in the main thread;
  • the run() method, which is defined in the Runnable interface. Since Thread1 implements this interface, you must implement the run() method in it. The run() method contains the main code for solving our task – the code for finding the maximum value;
  • accessor methods for class fields, the value of which is used in the main thread.

In this task, the main thread is the main() function, in which you need to perform the following steps:

  • declare the array to be tested;
  • create a child thread (an instance of the Thread1 class) and get a reference to it;
  • run the join() method so that the main thread ends up last;
  • after the completion of the child thread, read the result obtained in that thread.

The text of the program is as follows.

// The class that implements the child thread in the given task
class Thread1 implements Runnable {
  private Thread thr; // reference to the child thread
  private int[] AI;
  private int maximum; // Thread execution result

  // Constructor - gets an array of integers
  public Thread1(int[] _AI) {
    // Array initialization
    AI = _AI;

    // Create a thread
    thr = new Thread(this, "Thread1.");

    // Start a thread of execution
    thr.start();
  }

  // The method in which the thread execution code is written.
  // In our case, the code for finding the minimum value
  // and filling in the variable maximum is entered.
  public void run() {
    int max = AI[0];
    for (int i=1; i<AI.length; i++)
      if (max<AI[i]) max = AI[i];
    maximum = max;
  }

  // Access methods for class fields
  public Thread getThread() { return thr; }
  public int getMax() { return maximum; }
}

public class TrainThreads2 {

  public static void main(String[] args) {
    // 1. Declare the array under test
    int[] AI = { 2, 3, 4, 8, -1 };

    // 2. Create a child stream, get a reference to it
    Thread1 t1 = new Thread1(AI);

    // 3. Read the result
    try {
      // Waiting for the end of the thread t1 is mandatory,
      // otherwise you can get zeros
      t1.getThread().join();
    }
    catch (InterruptedException e) {
      System.out.println("Error.");
    }

    // Read the result after the end of stream t1
    System.out.println("max = " + t1.getMax());
  }
}

If you remove the code in the main() function

try {
  // Waiting for the end of the thread t1 is mandatory,
  // otherwise you can get zeros
  t1.getThread().join();
}
catch (InterruptedException e) {
  System.out.println("Error.");
}

then the following result will be obtained

max = 0

This means that the main thread exits first, without waiting for the child thread to finish. In this case, the original value of the variable maximum in the instance t1 is returned from the child thread. And this is a mistake.

Program execution result

max = 8

 

3. Method isAlive(). Determine if a thread is running. Example

The isAlive() method is designed to determine the existence (execution) of a thread. The general form of the method is as follows:

final boolean isAlive()

The method returns true if the thread on which the method is called is still running. Otherwise, it returns false.

Example. In the example, the isAlive() method waits for the child thread to terminate in order to obtain the result. In the child thread, the sum of the elements of an array of double type is calculated.

To get the correct sum, you need the main thread to finish last.

// A class that encapsulates the thread of execution.
class SumArray implements Runnable {
  Thread thr; // reference to the current thread
  double[] AD; // internal array reference
  double summ; // thread result

  // SumArray class constructor - gets the thread name and array
  SumArray(double[] AD, String name) {
    // Assign external reference to AD array
    this.AD = AD;

    // Create an instance of thr and set it to the name of the thread of execution
    thr = new Thread(this, name);

    // Start the thread for execution
    thr.start(); // The run() method is called
  }

  // The entry point into the thread is the run() method
  public void run() {
    // Message about the beginning of the thread execution - calculating the sum of the array
    System.out.println("SumArray.run() - begin");

    // in the stream, calculate the sum of the elements of the AD array
    // and write it to the summ variable
    summ = 0;

    for (int i=0; i<AD.length; i++) {
      try {
        // pause so that other threads can take control
        Thread.sleep(50);
        summ = summ + AD[i];
      }
      catch (InterruptedException e) {
        System.out.println(e.getMessage());
      }
    }

    // Thread completion message
    System.out.println("SumArray.run() - end");
  }

  // A method that returns the current thread
  Thread getThread() {
    return thr;
  }

  // Method that returns the sum of elements
  double getSumm() {
    return summ;
  }
}

public class Threads {

  public static void main(String[] args) {
    // Demonstration of the isAlive() method
    // 1. Declare an array for which you want to calculate the sum
    double[] AD = { 1.1, 2.2, 3.3, 4.4, 5.5, 6.6 };

    // 2. Create the instance of SumArray class
    SumArray sa = new SumArray(AD, "SumArray thread"); // thread is executed

    // 3. Call the isAlive() method in a loop
    //   to wait for the sa stream to end
    while (sa.getThread().isAlive());

    // 4. After the end of the child stream, get the sum
    double summ = sa.getSumm();
    System.out.println("summ = " + summ);
  }
}

In the above example, the delay is done by calling

while (sa.getThread().isAlive());

If you comment out this line, then the program can return a zero value of the sum. This is because the main thread will finish before the child thread finishes.

Program execution result

SumArray.run() - begin
SumArray.run() - end
summ = 23.1

 

4. Methods setPriority(), getPriority(). Set and get the priority of the thread. Example

As you know, different priorities can be set for threads of execution. High priority threads get most of the CPU time to run. In the Java language, it is possible to set the priority of threads. There are two methods for this:

  • setPriority() – sets the value of the priority of the thread;
  • getPriority() – reads (gets) the priority value of the thread.

In the Java documentation, the general form of methods is as follows:

final void setPriority(int level)
final int getPriority()

here

  • level – the priority level, which is set within the constants from MIN_PRIORITY to MAX_PRIORITY. The value of MIN_PRIORITY= 1, the value of MAX_PRIORITY = 10. If you need to set the default priority value, then the static constant NORM_PRIORITY is used for this, which is 5.

Example. The example demonstrates the creation of three threads with different priorities. An array of random integers is generated in each thread. To encapsulate the thread of execution, the RandomArray class is implemented, which contains the following components:

  • internal field thr – reference to the current thread of execution;
  • internal field AI – reference to the array of numbers;
  • constructor RandomArray(). The priority of the thread is set in the constructor and the thread is launched for execution;
  • the run() method, which generates an array of random numbers. This method is the entry point to the thread;
  • accessor methods for internal fields: getThread() and getArray();
  • getPriority() method, which returns the priority of the thread of execution. This method calls the thr instance method of the same name to get the numeric value of the priority.

 

// The class that encapsulates the thread of execution
class RandomArray implements Runnable {

  private Thread thr; // reference to the current thread
  private int[] AI; // an array of numbers

  // Class constructor SumArray.
  // Constructor gets the following parameters:
  // - name - name of thread;
  // - size - the size of the array to be generated in the thread;
  // - priority - thread priority.
  RandomArray(String name, int size, int priority) {
    // 1. Create the instance of thread
    thr = new Thread(this, name);

    // 2. Allocate memory for array AI
    AI = new int[size];

    // 3. Set priority
    //    Checking the priority value for correctness
    if ((priority>=Thread.MIN_PRIORITY)&&(priority<=Thread.MAX_PRIORITY))
      thr.setPriority(priority);
    else
      // if priority is incorrect, then set the default priority
      thr.setPriority(Thread.NORM_PRIORITY);

    // Start the thread for execution
    thr.start(); // the run() method is called - an array of numbers is generated
  }

  // The entry point into the thread is the run() method
  public void run() {
    // Message about the beginning of the thread execution - the name of the thread is indicated
    System.out.println(thr.getName() + " - begin");

    // in the thread, fill the array of integers with values from 1 to AI.length
    for (int i=0; i<AI.length; i++) {
      try {
        // pause so other threads can take control
        Thread.sleep(10);

        AI[i] = (int)(Math.random()*AI.length+1);
      }
      catch (InterruptedException e) {
        System.out.println(e.getMessage());
      }
    }

    // Thread completion message
    System.out.println(thr.getName() + " - end");
  }

  // Method that returns a reference to the current stream
  Thread getThread() {
    return thr;
  }

  // Method that returns a reference to the array of numbers
  int[] getArray() {
    return AI;
  }

  // Method that returns the priority of a thread
  int getPriority() {
    return thr.getPriority();
  }

  // Method that displays the AI array on the screen
  void Print(String text) {
    System.out.print(text + ".");
    System.out.print("AI = ");
    for (int i=0; i<AI.length; i++) {
      System.out.print(AI[i] + " ");
    }
    System.out.println();
  }
}

public class Threads {

  public static void main(String[] args) {
    try {
      // 1. Create three threads with different priorities
      RandomArray A1 = new RandomArray("A1", 1000, 7);
      RandomArray A2 = new RandomArray("A2", 1000, 2);
      RandomArray A3 = new RandomArray("A3", 1000, 22);

      // Wait for threads to finish
      A1.getThread().join();
      A2.getThread().join();
      A3.getThread().join();

      // 2. Display thread priorities for control
      System.out.println("A1 priority = " + A1.getPriority());
      System.out.println("A2 priority = " + A2.getPriority());
      System.out.println("A3 priority = " + A3.getPriority());
    }
    catch (InterruptedException e) {
      System.out.println(e.getMessage());
    }
  }
}

Program execution result

A2 - begin
A3 - begin
A1 - begin
A1 - end
A3 - end
A2 - end
A1 priority = 7
A2 priority = 2
A3 priority = 5

 


 Related topics