Multithreading in Java

In this article, we will learn what is multithreading and how to create multithreading programs in java with examples.
Let's quickly discuss theory about multithreading in Java.
Java provides built-in support for multithreaded programming. A multithreaded program contains two or more parts that can run concurrently. Each part of such a program is called a thread, and each thread defines a separate path of execution. Thus, multithreading is a specialized form of multitasking.
You are almost certainly acquainted with multitasking because it is supported by virtually all modern operating systems. However, there are two distinct types of multitasking:
  1. Process-based
  2. Thread-based.
Let's understand the difference between the two.
  1. A process is, in essence, a program that is executing. Thus, process-based multitasking is the feature that allows your computer to run two or more programs concurrently. For example, process-based multitasking enables you to run the Java compiler at the same time that you are using a text editor or visiting a website.
  2. In process-based multitasking, a program is the smallest unit of code that can be dispatched by the scheduler. In a thread-based multitasking environment, the thread is the smallest unit of dispatchable code. This means that a single program can perform two or more tasks simultaneously. For instance, a text editor can format text at the same time that it is printing, as long as these two actions are being performed by two separate threads. Thus, process-based multitasking deals with the “big picture,” and thread-based multitasking handles the details.
  3. Multitasking threads require less overhead than multitasking processes. Processes are heavyweight tasks that require their own separate address spaces. Interprocess communication is expensive and limited.
  4. Context switching from one process to another is also costly. Threads, on the other hand, are lighter weight. They share the same address space and cooperatively share the same heavyweight process. Interthread communication is inexpensive, and context switching from one thread to the next is lower in cost. While Java programs make use of process-based multitasking environments, process-based multitasking is not under Java’s control. However, multithreaded multitasking is.
Multithreading enables you to write efficient programs that make maximum use of the processing power available in the system. One important way multithreading achieves this is by keeping idle time to a minimum.

Defining and Starting a Thread

An application that creates an instance of Thread must provide the code that will run in that thread. Java provides two ways to create a thread programmatically.
  1. Implementing the Runnable interface.
  2. Extending the Thread class.
Read more on How to Create and Start a Thread in Java

Thread Class Overview

java.lang.Thread class creates a new thread of execution. It implements the Runnable interface. The Java Virtual Machine allows an application to have multiple threads of execution running concurrently.
Read more on Thread Class in Java

Let's discuss important methods of Thread Class with examples.

Thread.sleep() Method

Thread.sleep causes the current thread to suspend execution for a specified period. This is an efficient means of making processor time available to the other threads of an application or other applications that might be running on a computer system.
Thread class provides two overloaded versions of sleep method:
  1. static void sleep(long millis) - Causes the currently executing thread to sleep (temporarily cease execution) for the specified number of milliseconds, subject to the precision and accuracy of system timers and schedulers.
  2. static void sleep(long millis, int nanos) - Causes the currently executing thread to sleep (temporarily cease execution) for the specified number of milliseconds plus the specified number of nanoseconds, subject to the precision and accuracy of system timers and schedulers.

Thread join() Method

The join() method waits for a thread to die. In other words, it causes the currently running threads to stop executing until the thread it joins with completes its task.
The java.lang.Thread class has three overloaded versions of join methods:
  1. void join() - Waits for this thread to die.
  2. void join(long millis) - Waits at most millis milliseconds for this thread to die.
  3. void join(long millis, int nanos) - Waits at most millis milliseconds plus nanos nanoseconds for this thread to die.

getName() and setName(String name) Method

The java.lang.Thread class provides methods to change and get the name of a thread. By default, each thread has a name i.e. thread-0, thread-1 and so on. By we can change the name of the thread by using setName() method. The syntax of setName() and getName() methods are given below:
  • public String getName(): is used to return the name of a thread.
  • public void setName(String name): is used to change the name of a thread.
Thread class provides a static currentThread() - Returns a reference to the currently executing thread object.

setPriority(int newPriority) Method

Each thread has a priority. Priorities are represented by a number between 1 and 10.
In most cases, thread scheduler schedules the threads according to their priority (known as preemptive scheduling). But it is not guaranteed because it depends on JVM specification that which scheduling it chooses. 3 constants defined in Thread class:
  1. public static int MIN_PRIORITY
  2. public static int NORM_PRIORITY
  3. public static int MAX_PRIORITY Default priority of a thread is 5 (NORM_PRIORITY). The value of MIN_PRIORITY is 1 and the value of MAX_PRIORITY is 10.

Thread.interrupt() method

An interrupt is an indication to a thread that it should stop what it is doing and do something else. It's up to the programmer to decide exactly how a thread responds to an interrupt, but it is very common for the thread to terminate.
java.lang Thread class provides three interrupt() methods to work Interrupts properly.
  1. void interrupt() - Interrupts this thread.
  2. static boolean interrupted() - Tests whether the current thread has been interrupted.
  3. boolean isInterrupted() - Tests whether this thread has been interrupted.

Thread isAlive Method Example

java.lang.Thread class provides isAlive() method to test if this thread is alive or not. A thread is alive if it has been started and has not yet died.

ThreadGroup Class in Java

Java provides a convenient way to group multiple threads in a single object. Java thread group is implemented by java.lang.ThreadGroup class.
A thread group represents a set of threads. In addition, a thread group can also include other thread groups. The thread groups form a tree in which every thread group except the initial thread group has a parent.
A thread is allowed to access information about its own thread group, but not to access information about its thread group's parent thread group or any other thread groups.

Synchronization in Java

Let's understand what is synchronization and it's usage in multithreading programming.

When two or more threads need access to a shared resource, they need some way to ensure that the resource will be used by only one thread at a time. The process by which this is achieved is called synchronization.
There are two types of problems arise when multiple threads try to read and write shared data concurrently -
  1. Thread interference errors
  2. Memory consistency errors
The tool needed to prevent these errors is synchronization.
Let's discuss how to use synchronization to achieve how can only one thread access the shared resource.
We can synchronize our code in either of two ways. Both involve the use of the synchronized keyword.
  1. Using Synchronized Methods
  2. Using Synchronized Statement Or Block
Read more on Synchronization in Multithreading Java