Home Java Techniques to unlock the Power of Multi-Threading in Java

Techniques to unlock the Power of Multi-Threading in Java

Published: Last Updated on 0 comment

Hey, tea lovers! Today, we are going to tackle the topic of multithreading in Java. Have you ever heard the phrase “when doing one thing, prepare for another and execute a third”? This is the essence of multi-threading, where we perform multiple tasks concurrently. With Java, you can achieve this by creating multiple threads within your program.

When we talk about concurrency in Java we inherently talk about multi-threading. Multithreading refers to running multiple threads concurrently. Thread is just a lightweight sub-process. You can think of it as a mini process. Let us look at it by reading this post in your one thread and concurrently sipping that hot tea in another.


I would be happy to connect with you guys on social media. It’s @coderstea on TwitterLinkedinFacebook, Instagram, and YouTube.

Please Subscribe to the newsletter to know about the latest posts from CodersTea.


Introduction to Threading and Multi-Threading

What is a thread? As I said, a thread is a lightweight sub-process. They are the smallest units of processing. Your java program runs in a thread itself, called the main thread. Multithreading, as the name implies, performs or executes multiple threads concurrently. So that you don’t have to wait until the current job is done. You can just run the new job in another thread.

The question is how will you achieve multithreading in java? How can you drive a car, ride a bike, and sail a boat concurrently? For that to know to take another sip and continue reading.

You can find the code on GitHub here or the full project here. For an advanced level, you can manage multiple threads with a thread pool described in my “Recycle the Threads and Save the Resources with Thread Pool” post.

Make a Thread in Java for Multi-Threading

To run a multithreaded application Java needs to identify which code to run in a thread. The first step of suggestion is given by either extending the Thread class or implementing the Runnable interface. In both cases, you have to override the run() method. This method will contain the code that you need to run in a thread. Such as reading a file, hitting an API, or anything else.

After you are done with the run() function, you just need a Thread object. This object will spawn a new thread, on which your code will be executed. But Object creation doesn’t mean thread creation. You have to call the start() method.

This explanation to run the thread is very basic but you can execute it in many different ways. One is Thread Pool, which creates, reuses, and manages the threads for you. More on the thread pool here.

“Hmm, Hold on buddy, This information is too much to handle in one blow.” Apologies, Let’s break it down into multiple sips.

Thread Class in Java for Thread Creation

It’s simple, just extend the Thread class and override the run() method. Then create the object of the class and call start().

class MyThread extends Thread {
  @Override
  public void run() {
  // do something
  }
}

public class Main{
  publis static void main(String[] args){
   //  won't create the thread just now
    MyThread thread = new MyThread();
    thread.start(); // now a new thread is spawned.
  }
}Code language: JavaScript (javascript)

Now let’s look at the example with the car, bike, and Boat.

public class DriveACarRideTheBikesAndSailABoatConcurrently {
   public static void main(String[] args) {
     /*Extending the Thread */
     Car carThread = new Car();
     Thread bikeThread = new Bike();
     carThread.start();
     bikeThread.start();
   }
 }
 class Car extends Thread {
   @Override
   public void run() {
     for (int i = 0; i < 5; i++) {
       System.out.println("I am driving a Car on road " + i);
     }
   }
 }
 class Bike extends Thread {
   @Override
   public void run() {
     for (int i = 0; i < 5; i++) {
       System.out.println("I am riding a Bike on road " + i);
     }
   }
 }Code language: JavaScript (javascript)

Output:

I am driving a Car on road 0
I am riding a Bike on road 0
I am driving a Car on road 1
I am riding a Bike on road 1
I am driving a Car on road 2
I am riding a Bike on road 2
I am riding a Bike on road 3
I am riding a Bike on road 4
I am driving a Car on road 3
I am driving a Car on road 4

You can see in the output (your output may differ), the code is not behaving sequentially. You are driving and riding at the same time. One thing to notice here is that they are not running one by one or alternate. That is because of the nature of the threads. Whichever thread gets picked up by the CPU gets executed and others wait for the CPU to pick them up and the process continues. So don’t panic when they are not in order because they are asynchronous.

Runnable Interface in Java for Thread Creation

Thread is a class, but Runnable is an interface. Implement it and override run() and write your code in it. But to spawn a thread you need the start() method, which is not available in the Runnable interface. You will need a Thread object. And this Thread the object can be created by passing the runnable object to it. Just pass the Runnable object in the Thread constructor and that’s it. Or you can have an anonymous class as well. And using lambda it gets even more compact.

class MyThread implements Runnable {
  @Override
   public void run() {
    // do something
  }
}

public class Main{
  publis static void main(String[] args){
    // Runnable Object
    Runnable runnable = new MyThread();
   //  won't create the thread just now
    Thread thread = new Thread(runnable);
    thread.start(); // now a new thread is spawned.
  }
}Code language: PHP (php)

Now, let us explore different ways of creating Thread via Runnable Objects such as lambda and anonymous classes using boat and car.

public class DriveACarRideTheBikesAndSailABoatConcurrently {
   public static void main(String[] args) {
     /*Implementing Runnable */
     Runnable boatRunnable = new Boat();
     /*telling thread to execute run method from given Runnable */
     Thread boatThread = new Thread(boatRunnable);
     Thread boatAnonymousThread = new Thread(new Runnable() {
       @Override
       public void run() {
         for (int i = 0; i < 2; i++) {           System.out.println("I am sailing an anonymous boat in ocean" + i);         }       }     });     /*using lamda */     Thread boatLambdaThread = new Thread(() -> {
       for (int i = 0; i < 2; i++) {
         System.out.println("I am sailing a lambda boat in ocean" + i);
       }
     });
     boatThread.setName("Boat1");
     boatThread.start();
     boatAnonymousThread.start();
     boatLambdaThread.start();
   }
 }
 class Boat implements Runnable {
   @Override
   public void run() {
     for (int i = 0; i < 2; i++) {
       System.out.println("I am sailing a " + Thread.currentThread().getName() + " in ocean" + i);
     }
   }
 }Code language: PHP (php)

Output:

I am sailing a Boat1 in ocean0
I am sailing an anonymous boat in ocean0
I am sailing a lambda boat in ocean0
I am sailing an anonymous boat in ocean1
I am sailing a Boat1 in ocean1
I am sailing a lambda boat in ocean1

The War in Threading: Extends vs Implement

Which one to choose, should you extend or you should implement? The mighty Thread to extend or the Flexible Runnable to implement? It depends on the problem you are facing. But try to use implement it over extends if you have options. Why? Multiple inheritances are the cause. You can’t extend multiple classes but can implement multiple interfaces.

By implementing, you are free to implement and/or extends others. But in extends you are stuck with the same class forever and you are not allowed to go near others. Besides, you can use lambdas with Runnable.

Threading Creation to destruction: The life of a Thread

Thread’s life cycle is straightforward to understand. Just go through the following diagram.

multithreading-thread-lifecycle-flow
multithreading-thread-lifecycle-flow

When you create an Thread object it is in new sate. Calling start() puts it in the runnable state, then in running state. In the running state, it can go in either terminate if successful or an error occurs, or the wait state if CPU puts it on hold.

Thread Management

How do you control the thread? How to switch between states of a thread? Let us look at them one by one.

  • wait(): to put the thread in waiting the state.
  • notify: to migrate thread from waiting for the state to runnable state.
  • notifyAll(): notify all the threads to resume.
  • join(): Waits for this thread to die.
  • getName(): get the thread name.
  • setName(String name): to set the thread name.
  • <get or set >priority(): get or set the priority of the thread.

The last sip for Multi-Threading

There are plenty of other methods as well, but these are the functions you will use most of the time. And this information is enough for you to drive a car, ride bikes, and sail a boat concurrently.

That’s it for this cup of tea. This was a very basic intro to the Thread. You can find the code on GitHub here or the full project here. We will talk more about the advanced features for multithreading and best practices as well, like ThreadPool, CompletableFuture, etc. Thread pool is a very good approach when making multithreaded applications. You can read more about it in detail in my “Recycle the Threads and Save the Resources with Thread Pool“. So Just be ready with your next cup of tea.

See you in the next post. HAKUNA MATATA!!!


I would be happy to connect with you guys on social media. It’s @coderstea on TwitterLinkedinFacebook, Instagram, and YouTube.

Please Subscribe to the newsletter to know about the latest posts from CodersTea.


Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments
Ads
Ads
Ads

@2023 All Right Reserved. Designed and Developed by CodersTea

This website uses cookies to improve your experience. We'll assume you're ok with this, but you can opt-out if you wish. Accept Read More