Multithreading in Java – Everything You Need to Know

In Java, multithreading is defined as the process of executing multiple threads simultaneously. Here, a thread means the smallest unit of processing or in other words, a lightweight sub-process.

Both multithreading and multiprocessing can be used in order to achieve multitasking. But multithreading is used in Java rather than multiprocessing as a shared memory area is used by threads.

Multithreading saves memory as they don’t take up separate memory area and the processing time is also less as they take less time while context-switching among the threads. It is mainly used in animations and games.

Benefits of Java multithreading

  • The programmer does not get blocked by multithreading as the threads do not depend on each other and multiple operations can be carried out by the programmer at the same time.
  • Multithreading saves up time as multiple operations can be carried out at the same time.
  • In the case in which an exception occurs in one thread, other threads are not affected as the threads are not dependent on each other.

Multitasking

Multitasking can be defined as the process of carrying out multiple tasks at the same time. It is used in order to utilize the CPU. The two ways by which multitasking can be achieved are:

  • Process-based multitasking or Multiprocessing
  • Thread-based multitasking or Multithreading
  1. Process-based multitasking or multiprocessing

The main points to remember in multiprocessing are:

  • Each process takes up an address in the memory which means that each process takes up a separate memory area.
  • A process is a heavyweight.
  • The cost of communication in the process is high.
  • Switching from one process to another takes up some time for performing functions such as updating lists, saving and loading registers, and memory maps.
  1. Thread-based multitasking or Multithreading

The main points to remember in multithreading are:

  • All the threads allocate the same address space,
  • A thread is a lightweight.
  • The cost of communication among the threads is low.

What is a thread in Java?

In Java, a thread can be defined as the smallest unit of processing. It is a lightweight subprocess that is a distinct path of execution. Other threads are not affected when an exception occurs in one thread because the threads are not dependent on each other. A thread is executed inside a process and there is context-switching in the threads. Inside an OS there may be multiple processes and multiple threads can be within a process.

Java thread class

The thread class is supplied by the Java in order to achieve thread programming. The operations on a thread are created and performed by the constructors and methods provided by the thread class. The object class is extended by the thread class and it implements the Runnable interface as well.

Java thread methods

The various thread methods are explained below:

  1. void start():

This method starts the execution of the thread.

  1. void run():

This method carries out an action for the thread.

  1. static void sleep():

This method makes the thread sleep for a particular amount of time.

  1. static thread currentThread():

This method returns a reference to the thread object that is currently being executed.

  1. void join():

This method waits until a thread dies.

  1. int getPriority():

This method returns the priority of the specific thread.

  1. void setPriority():

This method changes the priority of the specific thread.

  1. string getName():

This method returns the name of the specific thread.

  1. void setName():

This method changes the name of the specific thread.

  1. long getId():

This method returns the id of the specific thread.

  1. boolean isAlive():

This method returns true if the thread is alive, otherwise returns false.

  1. static void yield():

This method allows threads to execute temporarily after the thread object that is currently being executed is paused.

  1. void suspend():

This method suspends the specified thread.

  1. void resume():

This method is used to resume the thread that has been suspended.

  1. void stop():

This method stops a specific thread.

  1. void destroy():

This method destroys a specific thread group and all of its subgroups.

  1. boolean isDaemon():

This method returns true if the thread is a daemon thread, otherwise returns false.

  1. void setDaemon():

This method is used to mark the thread as a daemon thread.

  1. void interrupt():

This method interrupts a specific thread.

  1. boolean isinterrupted():

This method returns true if the thread has been interrupted, otherwise returns false.

  1. static boolean interrupted():

This method returns true if the current thread has been interrupted, otherwise returns false.

  1. static int activeCount():

This method is used to find out the total number of threads in the current thread’s group that are active.

  1. void checkAccess():

This method checks whether the currently running thread has the permission to modify thread or not.

  1. static boolean holdLock():

This method is used to check if the current thread holds the monitor lock on a particular object or not.

  1. static void dumpStack():

This method prints a stack trace of the current thread to the standard error stream.

  1. StackTraceElement[] getStackTrace():

This method returns an array of stack trace elements that represent the stack dump of the thread.

  1. static int enumerate():

This method copies all active thread’s group and its subgroup into a particular array.

  1. State getState():

This method returns the state of the thread.

  1. ThreadGroup getThreadGroup():

This method returns the thread group that the thread belongs to.

  1. String toString():

This method returns a string representation of the thread which includes the name of the thread, its group, and priority.

  1. void notify():

This method provides the notification to one thread that is waiting for a specified object.

  1. void notifyAll():

This method provides the notification to all waiting threads of a specified object.

  1. void setContextClassLoader():

This method is used to set the context ClassLoader for a specific thread.

  1. ClassLoader getContextClassLoader():

This method is used to return the context ClassLoader for a specific thread.

  1. static Thread.UncaughtExceptionHandler getDefaultUncaughtExceptionHan:

This method is used to return the default handler called on when a thread abruptly terminates because of an uncaught exception.

  1. static void setDefaultUncaughtExceptionHandler():

This method is used to set the default handler called on in the case in which a thread abruptly terminates because of an uncaught exception.

The lifecycle of a thread (Thread states)

In general, there are five states that a thread can be. However, Sun has removed the running state so there are only four states and they are: new, runnable, non-runnable, and terminated.

But to better understand the concept of the thread, all of the five states will be dealt with in this chapter.

The Java thread states that are controlled by the JVM are as follows:

  1. New:

A thread is said to be in the new state before the invocation of the start() method when an instance of a thread is created.

  1. Runnable:

A thread is said to be in the runnable state when the start() method has been invocated but it has not been chosen by the thread scheduler as a running thread.

  1. Running:

A thread is said to in the running state after it gets chosen by the thread scheduler to run.

  1. Non-runnable (Blocked):

A thread is said to be in the non-runnable or the blocked state when it is alive but not currently eligible to run.

  1. Terminated:

A thread is said to be in the terminated state when the run() method is executed.

How to create a thread

There are two ways that can be used to create a thread and they are:

  1. By extending the thread class
  2. By implementing the runnable interface

Thread class

Various constructors and methods are provided by the thread class in order to create and carry out operations on a thread. The object class is extended by the thread class and it implements the runnable interface as well.

The commonly used constructors of the thread class:

Below are some of the most commonly used constructors of the thread class:

  • thread()
  • thread(string name)
  • thread(runnable r)
  • thread(runnable r, string name)

The commonly used methods of the thread class:

Some of the most commonly used methods of the thread class are explained below:

  1. public void run():

This method carried out an action for a specific thread.

  1. public void start():

This method starts the execution of the thread. The program invokes the run() method on the thread.

  1. public void sleep(long milliseconds):

This method makes the currently executing thread sleep for a particular number of milliseconds.

  1. public void join():

This method waits until a thread dies.

  1. public void join(long milliseconds):

 This method waits until a thread dies for a particular number of milliseconds.

  1. public int getPriority():

 This method returns the priority of the specific thread.

  1. public int setPriority(int priority):

This method changes the priority of the specific thread.

  1. public String getName():

 This method returns the name of the specific thread.

  1. public void setName(String name):

This method changes the name of the specific thread.

  1. public Thread currentThread():

This method returns a reference to the thread that is currently being executed.

  1. public int getId():

This method returns the id of the specific thread.

  1. public Thread.State getState():

This method returns the state of the thread.

  1. public boolean isAlive():

This method returns true if the thread is alive, otherwise returns false.

  1. public void yield():

This method allows threads to execute temporarily after the thread object that is currently being executed is paused.

  1. public void suspend():

This method suspends the specified thread.

  1. public void resume():

This method is used to resume the thread that has been suspended.

  1. public void stop():

This method stops a specific thread.

  1. public boolean isDaemon():

This method returns true if the thread is a daemon thread, otherwise returns false.

  1. public void setDaemon(boolean b):

This method is used to mark the thread as a daemon thread.

  1. public void interrupt():

This method interrupts a specific thread.

  1. public boolean isInterrupted():

 This method returns true if the thread has been interrupted, otherwise returns false.

  1. public static boolean interrupted():

This method returns true if the current thread has been interrupted, otherwise returns false.

Runnable interface

A class whose instances have been intended to be executed by a thread implements the runnable interface. The only method that is in the runnable interface is the run() method.

  • public void run():

This method is used to carry out an action for a specific thread.

Starting a thread:

A newly created thread is started by using the start() method. The following functions are carried out by it:

  • A new thread is started with a new call stack.
  • The thread transforms to the runnable state from the new state.
  • The run() method will get executed when the thread receives a chance to be executed.

Thread scheduler in Java

The thread scheduler is the part of the program that selects the thread to run. In a single process, only a single thread can be run and there is no assurance that which runnable thread will be selected to run. The preemptive or time slicing scheduling is used to schedule the threads by the thread scheduler.

An Simple example of single thread :

Dissimilarities between preemptive scheduling and time slicing

The highest priority task gets executed under the preemptive scheduling until it enters the waiting or dead states or another higher priority task gets created. But under the time slicing scheduling, a task gets executed for a specified slice of time and then enters to the pool of ready tasks. The scheduler then makes the decision on which task should be executed next on the basis of priority and other factors.

Sleep method in Java

In Java, the sleep() method of the thread class makes a thread sleep for a particular amount of time. The thread scheduler selects another thread to run when a thread is made to sleep for a particular time.

Thread.sleep()

Example:

The following are the two methods that are provided by the thread class to make a thread sleep:

  • public static void sleep(long milliseconds)throws InterruptedException
  • public static void sleep(long milliseconds, int nanos)throws InterruptedException

Can a thread be started twice?

A thread cannot be started twice. In other words, a thread can never be started again, once it has been already started. If the programmer tries to do so, an IllegalThreadStateException is thrown. That means the thread will only run a single time and in the second time, it will throw the exception.

What if the run() method is called directly instead of the start() method?

  • Each thread starts in a distinct call stack.
  • When the run() method is called on from the main thread, the run() method will not go to the beginning of a new call stack but it will go into the current call stack.

The join() method

The join() method waits until a thread dies. That means the join() method stops the currently running thread from executing until the thread it joins with finishes its job.

Syntax:

  • public void join()throws InterruptedException
  • public void join(long milliseconds)throws InterruptedException

getName(),setName(String) and getId() method:

  • public String getName()
  • public void setName(String name)
  • public long getId()

The currentThread() method:

The currentThread() method returns a reference to the thread object that is currently being executed.

Syntax:

  • public static Thread currentThread()

Naming thread and the current thread

Naming thread

There are methods provided by the thread class that is used in Java in order to get the name of a thread and to changes its name. The threads are named like thread-0, thread-1 and so on by default and the getName() method is used to find it. The name of the threads can be changed by using the setName() method.

Syntax:

  • public String getName():

This method returns the name of a specific thread.

  • public void setName(String name):

This method changes the name of a specific thread.

Priority of a thread (Thread priority):

Every thread in Java has a different priority. A number between 1 and 10 is used to represent these priorities. Preemptive scheduling of the thread scheduler schedules the threads on the basis of their priorities. But this is not always the case as the JVM specification selects the scheduling method to be used.

Three constants defined in thread class:

  • public static int MIN_PRIORITY:

The value of MIN_PRIORITY is 1.

  • public static int NORM_PRIORITY:

The value of NORM_PRIORITY is 5. This is the default priority of any thread.

  • public static int MAX_PRIORITY:

The value of MAX_PRIORITY is 10.

Daemon thread in Java

The daemon thread in Java is a type of thread that provides the services to the user thread. SO it is also known as a service provider thread. The daemon thread gets automatically terminated by the JVM when all the user thread dies. In other words, the life of daemon thread depends on the life of user threads.

There are various daemon threads that automatically runs in Java such as finalizer and gc. The detail on these threads can be seen by typing the jconsole in the command prompt. The jconsole tool also provides other useful information related to the memory usage, loaded classes, and running threads.

Main points to remember about the daemon thread in Java

  • The only function of the daemon thread is to serve user threads. It provides services to the user threads in carrying out background supporting tasks.
  • The life of a daemon thread is dependent on the life of the user threads.
  • The daemon thread is a thread with low priority.

Why is the daemon thread terminated when there is no user thread?

The only function of the daemon thread is to provide services the user threads in carrying out background supporting tasks. There is no point in running a daemon thread if there is no user thread in the JVM. Therefore, the JVM immediately terminates the daemon thread if there is no user thread.

Methods for Java daemon thread by the thread class

The following are the two methods provided by the java.lang.Thread class for the daemon thread:

  • public void setDaemon(boolean status):

This method marks the current thread as a daemon thread.

  • public boolean isDaemon():

This method returns true if the current thread is a daemon thread otherwise returns false.

Java Thread Pool

In Java, the thread pool is defined as a collection of worker threads that are waiting for a task and are reused many times. Here, a fixed size of threads is collected in a group. Then the programmer selects a thread from the thread pool and pulls it out and assigns a task to it. After the thread completes its task, it is contained in the thread pool again.

Benefits of Java thread pool

The thread pool makes the performance of the program better because there will be no need to create a new thread, the programmer can select a thread from the thread pool to complete a task.

Real-time usage

The thread pool is used in JSP and Servlet where it is used to process the request.

ThreadGroup in Java

There is a convenient way provided by the Java to group multiple threads in a single object. This way, the programmer can interrupt, resume, or suspend a group of threads by using only one method call. The java.lang.ThreadGroup class is used to implement the thread group in Java.

A set of threads is represented by a ThreadGroup and it can also have other thread groups inside it. The thread group creates a tree. In it, all the threads have a parent but not the initial thread group.

A thread group can only access the information about its own thread group but it is not allowed to access the information related to its thread group’s parent thread group or any other thread groups.

Constructors of ThreadGroup class

The following are the two constructors of the ThreadGroup class:

  • ThreadGroup(String name):

This constructor is used to create a thread group with the name provided by the programmer.

  • ThreadGroup(ThreadGroup parent, String name):

This constructor is used to create a thread group with the parent group and name that is given by the programmer.

Methods of ThreadGroup class

The following are the various methods used in the ThreadGroup class:

  1. void checkAccess():

This method is used to check whether the currently running thread has the permission to modify the thread group or not.

  1. int activeCount():

This method is used to estimate the number of active threads present in the thread group and its subgroups and then it returns the number.

  1. int activeGroupCount():

This method is used to estimate and return the number of active groups in the thread groups and its subgroups.

  1. void destroy():

This method is used to destroy a thread group and all its subgroups.

  1. int enumerate(Thread[] list):

This method is used to copy every active thread in the thread group and its subgroups into the specified array

  1. int getMaxPriority():

This method is used to return the maximum priority of the thread group.

  1. string getName():

This method is used to return the name of the thread group.

  1. ThreadGroup getParent():

This method is used to return the parent of the thread group.

  1. void interrupt():

This method is used to interrupt all threads in the thread group.

  1. boolean isDaemon():

This method returns true if the thread group is a daemon thread group otherwise return false.

  1. void setDaemon(boolean daemon):

This method is used to modify the daemon status of the thread group.

  1. boolean isDestroyed():

This method returns true if the thread group has been destroyed otherwise returns false.

  1. void list():

This method is used to print the information related to the thread group to the standard output.

  1. boolean parentOf(ThreadGroup g):

This method returns true if the thread group is either the thread group argument or one of its ancestor thread groups otherwise returns false.

  1. void suspend():

This method suspends all thread in the thread group.

  1. void resume():

This method resumes all the threads in the thread group that was suspended before with the suspend() method.

  1. void setMaxPriority(int pri):

This method is used to set the priority of the group to the maximum.

  1. void stop():

This method stops all the threads in the thread group.

  1. string toString():

This method is used to return a string representation of the thread group.

Java Shutdown Hook

The shutdown hook is used in Java when the program shuts down normally or abruptly to save the state of the code or to clean up the resources. Here, cleaning up the resources means closing log file and sending alerts. Therefore, the shutdown hook is used to execute codes before the program shuts down.

When does the JVM shut down?

The JVM shuts down in the following conditions:

  • When the programmer presses the ctrl+c on the command prompt.
  • When the user logs off.
  • When the System.exit(int) method is called on.
  • When the user shutdowns the program.

The addShutdownHook(Thread hook) method

The addShutdownHook() method registers the thread with the virtual machine. The syntax of this method is:

  • public void addShutdownHook(Thread hook){}

The static factory method getRuntime() is used to obtain the object of the runtime class.

Factory method

The factory method is used to return the instance of a class.

How to perform a single task by multiple threads?

Only one run() method is used when the programmer wants to perform one task by many threads.

How to perform multiple tasks by multiple threads?

Multiple run() methods are used when the programmer wants to perform multiple tasks by multiple threads.

Leave a Reply

Your email address will not be published. Required fields are marked *