Multithreading in Java in plain ‘English’

So, here’s the thing…

Before we talk about multithreading in Java, let’s talk about what a thread is;

A thread is the smallest unit of execution in a process a.k.a lightweight process

A thread is simply a series of executions of code. It’s actually much easier to define threads by understanding it. An illustration is, say this company has a database and about 4 eligible employees would like to make a request whether at the same time or not; each statement run by each of them represents a thread and the ability of the system to execute the 4 threads at the same time(concurrently) is multithreading.

Source: https://www.javatpoint.com/multithreading-in-java

A thread is a part of a process. Multiple threads can run in a process concurrently in a process called multithreading. In this case, resources are shared by the threads but resources are not shared across multiple processes. Multiprocessing is many processes running concurrently.

A process has a self contained execution environment with it’s own set of resources. A thread is lightweight because it requires fewer resources rather than creating another process.

Creating A Thread

In Java, a thread can be created in two ways; either by extending the Thread class or Implementing the Runnable Interface

By Implementing Runnable Interface

The Runnable interface has only one method, the run() method, which must be overridden. In this method, Thread class has to be instantiated and it’s constructor takes the class that implements Runnable as a parameter. Note that start() method is called on the thread if not, the thread won’t actually start running.

Output:

>> Thread running...

By extending the Thread class

The Thread class itself extends the Runnable interface but doesn’t actually do anything with run() method, so we just override it and since our class inherits Thread class, it inherits the start() method

Output:

>> Thread running...

There are many methods defined in the Thread class in Java. Some of the most commonly used methods are; run(), start(), sleep(long milliseconds), join(), join(long milliseconds), getPriority(), setPriority(int priority), getName(), setName(String name), currentThread(), interrupt(). I’ll only talk about a few here

You already saw the usage of run() and start() methods

sleep(long milliseconds) method

This methods pauses the current running thread for the specified time

In this program, we have two threads running. The sleep() method pauses the first thread after it executes for 1500ms and it runs the second thread which is then paused for 1500ms. This goes on till the program finish executing

Output:

>>Count 1
Count 1
Count 2
Count 2
Count 3
Count 3
Count 4
Count 4
Count 5
Count 5

join(), join(int milliseconds) method

This method lets all other running wait till a particular thread finish running

This program executes by running the first thread while the others wait for it to finish executing before they start executing.

Output of this program:

>>Count 1
Count 2
Count 3
Count 4
Count 5
Count 1
Count 1
Count 2
Count 2
Count 3
Count 3
Count 4
Count 4
Count 5
Count 5

The join(long milliseconds) takes a parameter which defines how long the thread runs before the rest of the threads start running.

This code runs the first thread for 2000ms before starting the remaining threads.

This outputs:

>>Count 1
Count 2
Count 1
Count 1
Count 3
Count 2
Count 2
Count 4
Count 3
Count 3
Count 5
Count 4
Count 4
Count 5
Count 5

Synchronization in Java

Sometimes, many threads might be accessing a particular shared resource and this might cause some inconsistency in the results. Using the little Database example earlier, you can think that a particular employee(thread) is trying to change/update the details of a particular entry in the database and at the same time another employee(thread) is trying to get information from the database on the that entry being changed, it’s very likely for some inconsistency and inaccuracies to occur afterwards. This is exactly what synchronization solves. Synchronization ensures that when a thread is locked in on a particular resource, no other thread can access that resource till the first thread is done through a concept called monitors; objects are assigned monitors which a thread can lock and unlock.

In java, you can create a synchronized method, block or even a synchronized static block using the keyword, “synchronized”

A program without synchronization:

Forgive my funny class names, I tried :-D

This program will keep generating different results because two threads are trying to access the same object reference “synco.count()” at the same time resulting in some inconsistency even after calling the join() method.

The program returns something like this:

>>Count 1
Count 2
Count 1
Count 2
Count 3
Count 4
Count 5
Count 3
Count 4
Count 5

This same program with synchronization:

This now results a consistent and correct result:

>>Count 1
Count 2
Count 3
Count 4
Count 5
Count 1
Count 2
Count 3
Count 4
Count 5

So… There you have it; just baby steps to understanding Multithreading in Java.

If you’d like to read more, this series by www.javatpoint.com is really good

Data Scientist/Software Developer.. Aspiring robotics engineer. Tech and Artificial Intelligence enthusiast

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store