Home » How Multi Threading Lets You do Things Simultaneously

How Multi Threading Lets You do Things Simultaneously

by Imran Shaikh
Published: Last Updated on 92 views
How Multi Threading Lets You Drive a Car, Ride the Bikes, and Sail a Boat Simultaneously

Hey, tea lovers! When doing a thing, prepare another, meanwhile, execute something else. Challenging, isn’t it? Let’s do the impossible with multi threading. You will learn it now if not before. The challenge is to do multiple things at once, parallelly. Oh, wait, are we talking about parallelization in programming?

Yes, precisely, multi-threading. So, When we talk about parallelization 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 sip that hot tea in another simultaneously.

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 simultaneously. 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 simultaneously? 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 as 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, reuse, and manages the threads for you. More on thread pool here.

“Hmm, Hold on buddy, This information is too much to handle in one blow.” Apologies, Let’s break it down in 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.
  }
}

Now lets look at the example with car, bike and Boat.

public class DriveACarRideTheBikesAndSailABoatSimultaneously {
   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);
     }
   }
 }

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), 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 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 in nature.

Runnable Interface in Java for Thread Creation

Thread is a class, but the Runnable is an interface. Implement it and override the run() and write your code in it. But to spawn a thread you need start() method, which is not available in the Runnable interface. You will need a Thread object. And this Thread 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 is 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.
  }
}

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

public class DriveACarRideTheBikesAndSailABoatSimultaneously {
   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);
     }
   }
 }

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 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 very easy to understand. Just go through the following diagram.

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

When you create a 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 state.
  • notify: to migrate thread from waiting state to runnable state.
  • notifyAll(): notify all the thread 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 simultaneously.

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 doing 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.

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

Privacy & Cookies Policy