Java Multithreading Tutorial With Example

Java Thread Example – How To Create a Thread

This guide will help you to understand Thread and its life cycle. We will create a few examples to create a thread using the Thread class and Runnable interface.

You will learn
– What is Thread in Java?
– Thread Life Cycle.
– How to create a thread using Thread class.
– How to create a thread using the Runnable interface.

Few more Multithreading Topics
– ThreadLocal example
– CompletableFuture tutorial with example
Concurrent Hashmap

Introduction to Thread

A Thread is nothing but a separate thread of execution.

In java, we can create background threads that will run concurrently along with the main thread to provide better performance.

Let’s understand the Thread concept using a real-life scenario.

If you have ever worked on MS World, then you may notice that while typing MS World also checks for the spelling error and when MS World finds any spelling error then it will notify the user.

The complete process doesn’t negatively impact the user.

Because when you type, MS Word checks for spelling mistakes in the background thread.

To put in other words, In a program, you can divide a few tasks to a few background threads to provide responsiveness and better user experience.

How to create a Thread in JAVA

There are two ways to create a Thread in Java.

  1. By extending Thread class.
  2. By implementing the Runnable interface.

Create a thread by extending the Thread class

The simplest way to create a thread using Thread class.

Task class is extending the Thread class that means it is a subclass of Thread class.

In order to specify what kind of work Task thread will perform, we will override the run() method of Thread class.

Now, let’s start the thread of execution.

From the above example, you could see that we have to call the start() method from thread’s reference.

When we call the start() method from the Thread reference, then run() method of that Thread will be executed.

If you run the above program, you will get below output

The above logs clearly indicate that there were two threads running during the execution. one was ‘main’ thread and another was ‘Thread-0’.

Create a Thread using Runnable Interface

We can also create a thread by implementing the Runnable interface.

Runnable Functional Interface
Runnable Functional Interface

Runnable is a functional interface with only one method run().

Therefore, instead of creating a class that implements the Runnable interface, we can also use the lambda expression to define a thread in one line.

Common Mistake : calling run() instead of start()

Many times people call run() method directly instead of start().

But it is not correct.

To understand why do you have to call start(), let’s see what happens internally when you call start() vs run().

Let’s change the above program and call run() from thread reference instead of start().

Execute the above program and focus on the output.

If you notice run() method was executed, but not from different threads.

Both of the statements were executed by the main thread only.

Therefore, we can conclude that when you call run() method from a thread reference then JVM will treat it like a normal function call and run() will be executed in the same thread (ex. main thread).

But when we call start() method from the thread reference, then JVM will register that thread with thread scheduler and call run() method.

How to give a name to threads

If you want to give a name to a thread, then you can call threadA.setName(String) or you can pass thread name in Thread constructor itself.

Thread Life Cycle

Thread Life Cycle
Thread Life Cycle

In the above example, we created an object of Thread.

It is not yet the thread of execution. It is just a Thread object as of now.

In other word, you can say the thread is in the newborn state.

When we call the start() method using thread reference, then it is eligible to run.

We can say that thread is in runnable state. Now it is up to thread scheduler and CPU’s time-slicing mechanism to run a runnable thread.

When thread scheduler allocates CPU then the thread will move to running state.

During execution thread may go back to runnable state due to sleep(), yield(), or join() call.

Or if thread completes its run() method execution, then it may go to a dead state.

IllegalThreadStateException

If you call start() method twice then you may get IllegalThreadStateException.

The above program will throw IllegalThreadStateException.

Thread Priority

If requires you can also change the priority of a thread.

Thread class provides three constant values to set the priority of a thread.

When we provide priority to a then, then thread scheduler may use it while allocating the CPU.

By default main thread’s priority would be 5 (NORM_PRIORITY)/

Conclusion

In this tutorial, we discussed Thread, How to create a Thread using Thread class and Runnable interface (Lambda expression).

We also discussed Thread Life Cycle, Thread Priority with a few examples.