Multithreading In Java: Explained


Pixels Hunter /

In a world of complex and resource-demanding applications, any optimization made to save resources is very welcomed by programmers. Luckily, multithreading technology allows us to accomplish this very thing.

Java, along with otherobject-oriented programminglanguages, offers a variety of resource-efficient tools. Today we ll be focusing on describing what multithreading is and how it works. We ll be examining code examples, and we hope this will reveal a crucial facet of programming that will improve whatever project you are working on.

What is Multithreading?

When you use an application it runs on a processing unit. Usually, computers possess one or more processing units, allowing us to use multiple applications at the same time.

But, to increase efficiency, programmers must find a way to use the power of just one processor to do many tasks. In Java, this is called multithreading and it s achieved when two or more processing tasks run in parallel.

Multithreading can be useful to save on resources, and it can easily improve the performance of any system, particularly when our CPU isn t all that powerful.

But how does multithreading work? Programs can run sequentially by executing the code line by line, one after the other, in a single-thread fashion. But with multithreading, we can define multiple portions of code that when executed will start simultaneously. This is what the term threads refers to parts of code that run in parallel.

As programmers, we have another alternative called multiprocessing, that in opposition to multithreading, needs two or more CPU processors to run programs. These two are the major multitasking paradigms, and we ll leave multiprocessing for another article. Let s focus on this concept of threads .

Java Threads Lifecycle

Threads are the foundation of any simple or complex computer program. They are a code unit that gets a task done, and once it s finished commands what the next task is that the computer should process.

When we build programs using multiple threads, multiple virtual units are created, in a similar way to how a CPU can have multiple cores. One great advantage that multithreading has is derived from this fact: if errors occur in one thread, none of the others are affected.

The lifecycle of a Java thread is the multiple states it takes during the running time of our code.

We call the first stage New , and it occurs when a thread is created. It s finished once we define a task for it. Then, the next stage is called Runnable . It happens once we define a task and the thread is ready to start working on it. The magic of multithreading happens precisely after a thread becomes runnable, as it s after this point that it saves us resources.

After this, the Running stage begins when we give the thread the command to start and finishes precisely when the task is done. Waiting is a non-linear stage that occurs when our thread needs to wait for another thread to finish before it can continue processing its task.

Finally, the Dead stage is reached when the thread finishes the task and no further processing is necessary.

An Example of Lifecycles in Java

This is what that can look like in a code example:

public class ThreadLifecycleDemo {
    public static void main(String[] args) {
        // Create a new thread
        Thread thread = new Thread(() -> {
            System.out.println("Thread is running.");

            try {
                // Simulate some work being done
            } catch (InterruptedException e) {

            System.out.println("Thread has completed its work.");

        // Start the thread

        // Wait for the thread to finish
        try {
        } catch (InterruptedException e) {

        System.out.println("Main thread exiting.");

Here, you see that a thread is created using a lambda expression. After defining it, the thread starts by printing that it is running to the console. Then it sleeps for two seconds and then prints that it has completed its work.

The main method starts the thread by calling the start method. This means that everything in the code will be executed simultaneously. After the thread is started, we call join so that we only print the final string after the thread has finished running. This is a precautionary measure more than anything else, and don t worry about methods, as we ll be talking about them next.

While this might seem like a cheeky example, we can build more complex applications upon it, as we ll see in just a second.

An example of threads implemented in Java.

Thread Class and Methods

Java is by far the best language to develop an understanding of multithreading because it widely supports this programming approach. It even provides many methods to make multithreaded programs as powerful as possible!

These methods, alongside withconstructors, are available when we use the Java Threadclass, which extends the Objects class and allows us to use the Runnable interface. Let s see some of them.

  • The start() and stop() methods initiate and terminate the thread s execution.
  • The run() method executes a thread without creating a new one.
  • The currentThread() method returns the thread we are currently located at.
  • The isAlive() method allows us to know if a thread is alive (running) or dead (terminated), and the sleep() method temporarily suspends the thread.
  • The yield() method allows us to tell the task scheduler to reorganize the thread s execution order.
  • The suspend() method does the same, but we can specify an event that will restart our thread when it occurs. We can use the resume() method to resume the execution of a suspended thread immediately.
  • The interrupt() method stops a thread that may be waiting for another action to happen.
  • The destroy() method stops the execution of thread groups or subgroups.

Multithreading can be quite difficult to understand practically, especially if you are a beginner programmer. But don t worry! We have some examples for you in the next section, so keep reading.

Multithreading Syntax And Examples

We have two ways to create threads in Java, and each one is useful for different situations. The first method is using the Thread class which, as we saw before, offers a variety of methods and constructors.

The second method means using the Runnable interface, whose instances are designed to be used by threads. It s very useful when we want to use the same class in several threads simultaneously. Let s look at an example:

class Multi extends Thread{
    public void run(){
        System.out.println("thread is running...");
    public static void main(String args[]){
        Multi thread1=new Multi();
A thread is implemented using the Thread class.

The above example shows how to create a new thread by extending the Thread class. The start() method is the first and most important method used.

The method tells the computer that our thread is now Runnable when previously it was in the New state. When the task scheduler allows it, the run() method is commanded and the thread starts working on its task.

Now, let s see an example that shows how to implement the Runnable interface.

class Multi3 implements Runnable{
    public void run(){
        System.out.println("thread is running with runnable...");
    public static void main(String args[]){
        Multi3 m1 = new Multi3();
        Thread thread1 = new Thread(m1);

Once again, the output of this code will be:

An example of a thread implemented using Runnable interface.

As you see, there isn t much complexity in the syntax once you understand the concept. However, you can keep these examples for future reference in case you ever need them.

Multithreading in a Real-Life Situation

Here s a more complex example of what multiple threads working simultaneously might look like in a real-world situation. Keep an eye out for the declarations of threads and the use of methods.

class MyThread extends Thread {
    public void run() {
        try {
            for (int i = 1; i 
A more complex example of different threads implemented in the same program.

This is a simple program that will print a series of integers with a delay of 1 second between each iteration. We create three threads as instances of mythread , within the main method of the MultithreadingExample class. Then we use the run() method we mentioned earlier to initiate them.

Then, after the program has successfully printed all the numbers, the join method makes sure that the final message is only printed after every thread has reached its dead stage. This means that running this program will cause each thread to print its ID and a series of integers from 1 to 5 (you could of course specify others), with a 1-second delay between each value. Finally, the program will print All threads have finished executing .

Multithreading In Java: Explained

That s about it: we ve covered every fundamental concept necessary for you to understand what multithreading is and how to approach it.

First, we went through the theory and reviewed the computer process that occurs behind the curtains. Also, we established the difference between multithreading and multiprocessing.

Then, we learned about threads and what they mean in the multithreading paradigm. Moreover, we reviewed every stage that forms its lifecycle. Another important thing we talked about was multithreading methods and what they do. The list we provided should be enough for you to start experimenting on your own.

Leave a Comment