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:
- Thread()
- Thread(String name)
- Thread(Runnable r)
- Thread(Runnable r, String name)
- Thread(ThreadGroup group, Runnable target)
- Thread(ThreadGroup group, Runnable target, String name)
- Thread(ThreadGroup group, Runnable target, String name, long stackSize)
- 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:
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.
As the above diagram shows, a thread always exists in any one of the following five states:
- New
- Active
- Blocked / Waiting
- Timed Waiting
- 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.