Java

Drive a car, ride the bikes, and sail a boat simultaneously: MultiThreading

 0

 15

By Imran.shaikh

On Mar 21, 2020 at 09:47 am

  

Introduction

When doing a thing, prepare another, meanwhile, execute something else. But how? How will you multitask? No problem, you will learn it now if not before. When we talk about parallelization in Java we inherently talk about multithreading. 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.

 

Introduce it, please

What is a thread? Like I discussed, a thread is a lightweight sub-process. They are the smallest units or 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 this job is done. You can just operate the new one in another thread. And how will you achieve multithreading in java? How I can 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.

 

Make a Thread

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, which is the second mark to identification or I would say the function thread will execute. Now that you are done with the code which will run simultaneously to the main thread, you just need a Thread object. This object will trigger the thread to run via start(). The aforementioned explanation is basic and you can execute it in many ways. “…Hold on buddy, This information is too much to handle in one blow.” Apologies, Let’s break it down in multiple sips.

 

Thread.java

Just extend the Thread class and override the run() method. Thread create the object of the class and call start(). Look at the code, please.

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 procedural. You are driving and riding at the same time. One thing to notice here is that they are not in running one by one or alternate. That because of the nature of the threads. Whichever thread gets picked up by the CPU to execute it runs, others wait and vice versa. So don’t panic when they are not in order. They are async, to begin with.

 

Runnable.java

Thread is a class, but the Runnable is the interface. Implement it and override the run() and write your code in it. But to call start() you need Thread object then how we will call the thread? 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 is even more compact.

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 an 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 an lambda boat in ocean0
I am sailing an anonymous boat in ocean1
I am sailing a Boat1 in ocean1
I am sailing an lambda boat in ocean1

 

Extend vs Implement

Which one to choose? 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.

 

Creation to destruction: The life of a Thread

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

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.

 

The 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

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 the 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 advanced features for multithreading and best practices as well, like ThreadPoolCompletableFuture, etc. So Just be ready with your next cup of tea.

   JavaJava8MultiThreadingConcurrency

About Contributer

Questions / Comments


Comments

Be the first to comment on this post.