Important Concepts of Object-Oriented system (Part V)

6. Concurrency

Introduction

Concurrency means simultaneously execution of more than one thread. Some that are transitory and others that last for the entire execution cycle. An application running on multi-core systems allow truly concurrent threads of control, whereas application running on a single core creates an illusion by using time-slicing algorithm. Concurrency enables a program to achieve high performance and throughput by utilizing the untapped capabilities of the underlying OS and machine hardware.

At a high level, there are two kinds of concurrency

· Heavyweight concurrency — Process that is independently managed by OS and have its own address space.

· Lightweight concurrency — Process that lives within a single operating system’s process along with other lightweight processes, which share the same address space.

In Heavyweight, processes communicate using IPC (i.e. Sockets and Pipe) whereas lightweight process shares data among themselves.

The process has a self- contained execution environment (i.e. own memory space). Process communicate among themselves either in the same or different system using IPC (Inter Process Communication) such as sockets and pipes. Most implementation in JVM runs as a single process. we can create additional process using ProcessBuilder class.

Concurrency focuses on process abstraction (i.e. each object may have a separate thread of control) and synchronization (i.e. How each active objects synchronise their activities and state among each other).

According to Grady Booch, we can achieve concurrency in Object-oriented design by three approaches: -

a) Concurrency is an intrinsic feature of certain programming languages, which provides a mechanism for concurrency and abstraction. In this case, we may create an active object that runs some process concurrently with all other active objects.

b) We may use class libraries that implement some form of lightweight processes which is not an intrinsic part of the language but appears as it is intrinsic.

c) We may use interrupts to give us the illusion of concurrency.

Let’s see how can we achieve concurrency in java

In Java, we can achieve concurrency using threads. Thread is a lightweight process which has its own call stack but can access shared data of other threads in the same process.

Thread is defined in java.lang package. we can use java.lang.Runnable interface to abstract the thread behaviour out of thread class.

There is by default one thread i.e. main() thread. This thread can create additional threads.

Benefits of Thread Object: -

· To instantiate the asynchronous task.

· To abstract thread management from the rest of our application by passing the application’s task to an executor.

· To allow concurrent execution of two or more code snippet for maximum CPU utilization.

Thread Lifecycle

Thread Lifecycle

· New — when we create an instance of Thread class.

· Running — when a thread is in running state.

· Suspend — A running thread can be suspended which suspend its activity. A suspended thread can then be resumed, allowing it to pick up where it left off.

· Blocked — Thread cab be blocked when waiting for a resource.

· Terminated — A thread can be terminated. Which halts its execution immediately at any given time for the resource. Terminated thread can’t be resumed.

Thread creation: -

We can create threads in two ways: -

1. By extending Thread class (java.lang.Thread)

2. By implementing Runnable interface (java.lang.Runnable)

By extending Thread class: -

//MultiThread.java
package com.thirstybrain.app.thread;

Things to consider while creating a thread using Thread class: -

  1. Extend Thread class

2. Override run()method in the extended class(i.e. MultiThread) and write code snippet which needs to invoke using thread.

3. Create an instance of an extended class (i.e. MultiThread)

4. Invoke start() method using MultiThread class. start() method will call run() method internally.

By implementing the Runnable interface: -

EX: -

//MultiThread.java
package com.thirstybrain.app.thread;

Threads Important methods –

· start()- To begin the thread execution.

· run()- To run the thread.

· interrupt () - To interrupt the thread. When we call this method os throws InterruptException, if the thread is waiting due to the method like wait(), join(), sleep().

· isinterrupted()- To test whether the thread has interrupted. The interrupted status of thread is not affected.

· yield() — It initiates the scheduler that current thread is willing to yield its current use of the processor. Use this function into CPU intensive code to prevent inconsistencies in OS that are preemptive.

How to manage asynchronous in java?

By using Synchronized keywords, it only allows one thread at a time into a particular section of code to execute. It uses the monitor concept. Monitor is an object, used for mutual exclusive lock over a resource till the completion, other thread will wait for their turn to occupy the resource.

EX: -

synchronized(sync_object){
// access shared resources
}

[NOTE: Too many uses of the synchronized block will also degrade the performance of the application. So use it wisely.]

Common issues and solutions: -

While designing a complex application, it is very hard to control multiple threads. It results following below issues while execution: -

· Livelock — A thread often acts in response to the action of another thread. If the other thread’s action is also a response to the action of another thread but both threads are unable to make further progress

· Starvation — The state where one (or more) thread is deprived of a chance to access an object. The problem can be solved by setting the correct priority to all the threads.

· Race condition — Two threads are working simultaneously on the same variable and at least one thread tries to write a value to the variable. So there will be a race among the two thread who will change the value.

· Deadlock — Two threads wait for each other to complete the operation before performing the individual action as a result two threads are locked and the program fails.

Frameworks which we can use to manage threads

· Executor Framework- It is used when our application has some requirement where we’ve to execute the tasks by multiple threads concurrently, so if we use this framework we need not have to manage the threads. we can just define the number of threads to be in the thread pool and that’s it.

· Fork and join Framework- It is used when we’ve some sort of task that we can divide into a small task and then join them to get the final result.

[NOTE: Too many threads could induce CPU to spend more time in changing context than actual code execution. In result, it will degrade the application’s performance.]

Conclusion:

This article is all about Object-oriented perspective of concurrency and how to achieve it programmatically. How to manage thread? What are the common issues we are encountering while dealing with threads and frameworks available in the market to manage threads?

Important Concepts of Object-Oriented system (Part I)

Important Concepts of Object-Oriented system (Part II)

Important Concepts of Object-Oriented system (Part III)

Important Concepts of Object-Oriented system (Part IV)

--

--

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
Kumar Shivam

Technical Consultant | Passionate about exploring new Technology | Cyber Security Enthusiast | Technical Blogger | Problem Solver