JavaWhat is the Java Thread Class?

What is the Java Thread Class?

In our Java concurrency tutorial, we learned that the Thread class is the main class upon which Java’s multithreading system is based. It, along with the Runnable interface are what make multithreading possible in Java. Although developers can implement the Runnable interface to run a piece of code a separate thread, there is really no requirement to do so, as the Thread class already implements it. Moreover, it provides several constructors and methods to support multithreading. In today’s programming tutorial, we will be exploring how to use the Thread class’s constructors and methods in our Java applications.

Check out our previous article on Java Concurrency for more.

Java Thread Class Constructors

As you might imagine, keeping tabs on all of your active threads can be a daunting task. For that reason, Java’s Thread class comes equipped with several constructors that allow you to name your Threads and even assign them to groups. Java’s Thread class constructors include:

  1. Thread()
  2. Thread(String name)
  3. Thread(Runnable r)
  4. Thread(Runnable r, String name)
  5. Thread(ThreadGroup group, Runnable target)
  6. Thread(ThreadGroup group, Runnable target, String name)
  7. Thread(ThreadGroup group, Runnable target, String name, long stackSize)
  8. Thread(ThreadGroup group, String name)

Here is an example Java Program illustrating how to set the name of a thread at time of creation. It also refers to the thread’s name inside the run() method:

import java.io.*;

class ThreadNamingExample extends Thread {
  
  // The subclass must also include the constructor
  // in order to use it  
  ThreadNamingExample(String name) {
    // Call the Thread class constructor
    super(name);
  }
  
  @Override 
  public void run() {
    System.out.println(this.getName() + " is running.....");
  }
  
  public static void main(String[] args) {
    
    // Create two threads
    ThreadNamingExample t1 = new ThreadNamingExample("Thread 1");
    ThreadNamingExample t2 = new ThreadNamingExample("Thread 2");
    
    // Get the above created threads' names.
    System.out.println(t1.getName() + " has started.");
    System.out.println(t2.getName() + " has started.");
    
    // Starting threads using start() method
    t1.start();
    t2.start();
  }
}

We can see the program along with its produced output below:

Java Thread tutorial

It is worth mentioning that there is also a setName() method, so you can update a Thread’s name at any time.

Read: IntelliJ IDEA Review

How to Fetch the Name of the Current Thread in Java

In the above code example, we called the class’s getName() method directly via the this pointer. Another way to obtain a reference to the active thread name is to invoke the static Thread.currentThread() method. We could then call getName() on the returned thread:

@Override 
public void run() {
  System.out.println(Thread.currentThread().getName() + " is running.....");
}

The Thread Lifecycle in Java

Now that we have covered some Thread basics, this might be a good time to go over the lifecycle of a thread and it’s many states. The following diagram shows the different states involved in the life cycle of a thread.

Java Thread Lifecycle

 

As the above diagram shows, a thread always exists in any one of the following five states:

  1. New
  2. Active
  3. Blocked / Waiting
  4. Timed Waiting
  5. Terminated

Programmers can get a thread’s current state at any time by invoking the getState() method. Here is a Java code example that employs it to show some of the thread states defined above:

public class ThreadStateDemo extends Thread {
	public static Thread t1;  
	public static ThreadStateDemo threadStateDemo;  
	
	class Thread2 extends Thread {  
		public void run() {    
		  
			try {  
				// move thread t2 to the state timed waiting  
				Thread.sleep(100);  
			}  
			catch (InterruptedException ie) {  
				ie.printStackTrace();  
			}  
			  
			System.out.println(
				"The state of thread t1 while it invoked the method join() on thread t2 -"
				+ t1.getState()
			);  
			   
			try {  
				Thread.sleep(200);  
			}  
			catch (InterruptedException ie) {  
				ie.printStackTrace();  
			}     
		}  
	}  
	
	public static void main(String[] args) {
		threadStateDemo = new ThreadStateDemo();  
		t1 = new Thread(threadStateDemo);  
		  
		// thread t1 is spawned   
		// The thread t1 is currently in the NEW state.  
		System.out.println("The state of thread t1 after spawning it - " + t1.getState());  
		  
		// invoke the start() method on the thread t1  
		t1.start();  
		  
		// thread t1 is moved to the Runnable state  
		System.out.println(
		  "The state of thread t1 after invoking the method start() on it - " 
		  + t1.getState()
		);  
	}

	public void run() {  
		Thread2 thread2 = new Thread2();  
		Thread t2 = new Thread(thread2);  
		  
		// thread t2 is created and is currently in the NEW state.  
		System.out.println("The state of thread t2 after spawning it - "+ t2.getState());  
		t2.start();  
		  
		// thread t2 is moved to the runnable state  
		System.out.println(
			"the state of thread t2 after calling the method start() on it - " 
			+ t2.getState()
		);  
		  
		try {  
			// move the thread t1 to the state timed waiting   
			Thread.sleep(200);  
		}  
		catch (InterruptedException ie) {  
			ie.printStackTrace();  
		}  
		  
		System.out.println(
			"The state of thread t2 after invoking the method sleep() on it - "
			+ t2.getState()
		);  
		   
		try {  
			// wait for thread t2 to complete its execution  
			t2.join();  
		}  
		catch (InterruptedException ie) {  
			ie.printStackTrace();  
		}  
		System.out.println(
			"The state of thread t2 when it has completed it's execution - " 
			+ t2.getState()
		);  
	}  
}

Running the program prints the following output to the console:

The state of thread t1 after spawning it - NEW
The state of thread t1 after invoking the method start() on it - RUNNABLE
The state of thread t2 after spawning it - NEW
the state of thread t2 after calling the method start() on it - RUNNABLE
The state of thread t1 while it invoked the method join() on thread t2 -TIMED_WAITING
The state of thread t2 after invoking the method sleep() on it - TIMED_WAITING
The state of thread t2 when it has completed it's execution - TERMINATED

The above program also showcased the join() method, which waits for the calling thread to complete its execution. That is why the next call to getState() returned a Thread.State enum value of TERMINATED.

Read: Top Java Frameworks

Final Thoughts on the Java Thread Class

In this follow-up to the Java concurrency tutorial, we learned how to use the Thread class’s many constructors and methods in our Java applications. With a little under forty methods, there is a lot more to the Thread class than covered here. You can see the full listing in the official docs.

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Latest Posts

Related Stories