You are on page 1of 45

Java Multi-threading Evolution and Topics

By Lokesh Gupta | Filed Under: Multi Threading

One of our reader, Anant, asked this extremely good question to elaborate / list down
all related topics that we should know about multi-threading including changes made in
java 8.( Beginner level to Advance level). All he wanted to know was evolution of Multi-
threading Framework in Java from Simple Runnable interface to latest feature in Java 8.
Let us solve his query.

I spent good amount of time in collecting all below information. So please feel free to
suggest edit/update in below information if you think otherwise on any point.

JDK release-wise multi-threading concepts


As per JDK 1.x release, there were only few classes present in this initial release. To be
very specific, there classes/interfaces were:

 java.lang.Thread
 java.lang.ThreadGroup
 java.lang.Runnable
 java.lang.Process
 java.lang.ThreadDeath
 and some exception classes

e.g.

1. java.lang.IllegalMonitorStateException
2. java.lang.IllegalStateException
3. java.lang.IllegalThreadStateException.

It also had few synchronized collections e.g. java.util.Hashtable.

JDK 1.2 and JDK 1.3 had no noticeable changes related to multi-threading. (Correct me
if I have missed anything).

JDK 1.4, there were few JVM level changes to suspend/resume multiple threads with
single call. But no major API changes were present.

JDK 1.5 was first big release after JDK 1.x; and it had included multiple concurrency
utilities. Executor, semaphore, mutex, barrier, latches, concurrent
collections and blocking queues; all were included in this release itself. The biggest
change in java multi-threading applications cloud happened in this release.

Read full set of changes in this


link: http://docs.oracle.com/javase/1.5.0/docs/guide/concurrency/overview.html

JDK 1.6 was more of platform fixes than API upgrades. So new change was present in
JDK 1.6.

JDK 1.7 added support for ForkJoinPool which implemented work-stealing


technique to maximize the throughput. Also Phaser class was added.

JDK 1.8 is largely known for Lambda changes, but it also had few concurrency changes
as well. Two new interfaces and four new classes were added
in java.util.concurrent package e.g. CompletableFuture and CompletionException.

The Collections Framework has undergone a major revision in Java 8 to add aggregate
operations based on the newly added streams facility and lambda expressions;
resulting in large number of methods added in almost all Collection classes, and thus in
concurrent collections as well.

Read full set of changes in this


link: http://docs.oracle.com/javase/8/docs/technotes/guides/concurrency/changes8.html

References:
 https://www.cs.princeton.edu/courses/archive/fall97/cs461/jdkdocs/relnotes/intro.
html
 http://programmers.stackexchange.com/questions/147205/what-were-the-core-
api-packages-of-java-1-0
 http://docs.oracle.com/javase/1.5.0/docs/guide/concurrency/overview.html
 http://docs.oracle.com/javase/7/docs/technotes/guides/concurrency/changes7.ht
ml
 http://www.oracle.com/technetwork/java/javase/jdk7-relnotes-418459.html
 http://docs.oracle.com/javase/8/docs/technotes/guides/concurrency/changes8.ht
ml

I hope that above listings will help you understanding the multi-threading features
JDK version wise.

Happy Learning !!
Java Concurrency – Thread Safety?
By Lokesh Gupta | Filed Under: Multi Threading

Defining thread safety is surprisingly tricky. A quick Google search turns up numerous
“definitions” like these:

1. Thread-safe code is code that will work even if many Threads are executing it
simultaneously.
2. A piece of code is thread-safe if it only manipulates shared data structures in a
manner that guarantees safe execution by multiple threads at the same time.

And there are more similar definitions.

Don’t you think that definitions like above actually does not communicate anything
meaningful and even add some more confusion. Though these definitions can’t be ruled
out just like that, because they are not wrong. But the fact is they do not provide any
practical help or perspective. How do we make a difference between a thread-safe
class and an unsafe one? What do we even mean by “safe”?

What is Correctness in thread safety?


At the heart of any reasonable definition of thread safety is the concept of correctness.
So, before understanding the thread-safety we should understand first, this
“correctness“.

Correctness means that a class conforms to its specification.

You will agree that a good class specification will have all information about a class’s
state at any given time and it’s post condition if some operation is performed on it.
Since we often don’t write adequate specifications for our classes, how can we possibly
know they are correct? We can’t, but that doesn’t stop us from using them anyway once
we’ve convinced ourselves that “the code works”. This “code confidence” is about as
close as many of us get to correctness.

Having optimistically defined “correctness” as something that can be recognized, we can


now define thread safety in a somewhat less circular way: a class is thread-safe when it
continues to behave correctly when accessed from multiple threads.

A class is thread-safe if it behaves correctly when accessed from multiple threads,


regardless of the scheduling or interleaving of the execution of those threads by the
runtime environment, and with no additional synchronization or other coordination on
the part of the calling code.

If the loose use of “correctness” here bothers you, you may prefer to think of a thread-
safe class as one that is no more broken in a concurrent environment than in a
single-threaded environment. Thread-safe classes encapsulate any needed
synchronization so that clients need not provide their own.

Example: A Stateless Servlet


A good example of thread safe class is java servlets which have no fields and references,
no fields from other classes etc. They are stateless.

public class StatelessFactorizer implements Servlet


{
public void service(ServletRequest req, ServletResponse resp)
{
BigInteger i = extractFromRequest(req);
BigInteger[] factors = factor(i);
encodeIntoResponse(resp, factors);
}
}

The transient state for a particular computation exists solely in local variables that are
stored on the thread’s stack and are accessible only to the executing thread. One thread
accessing a StatelessFactorizer cannot influence the result of another thread accessing
the same StatelessFactorizer; because the two threads do not share state, it is as if
they were accessing different instances. Since the actions of a thread accessing a
stateless object cannot affect the correctness of operations in other threads, stateless
objects are thread-safe.

That’s all for this small but important concept around What is Thread Safety?

Happy Learning !!
Concurrency vs. Parallelism
By Lokesh Gupta | Filed Under: Multi Threading

Concurrency means multiple tasks which start, run, and complete in overlapping time
periods, in no specific order. Parallelism is when multiple tasks OR several part of a
unique task literally run at the same time, e.g. on a multi-core processor. Remember that
Concurrency and parallelism are NOT the same thing.

Let’s understand more in detail that what I mean when I say Concurrency vs.
Parallelism.

Concurrency
Concurrency is essentially applicable when we talk about minimum two tasks or more.
When an application is capable of executing two tasks virtually at same time, we call it
concurrent application. Though here tasks run looks like simultaneously, but essentially
they MAY not. They take advantage of CPU time-slicing feature of operating system
where each task run part of its task and then go to waiting state. When first task is in
waiting state, CPU is assigned to second task to complete it’s part of task.

Operating system based on priority of tasks, thus, assigns CPU and other computing
resources e.g. memory; turn by turn to all tasks and give them chance to complete. To
end user, it seems that all tasks are running in parallel. This is called concurrency.

Parallelism
Parallelism does not require two tasks to exist. It literally physically run parts of tasks OR
multiple tasks, at the same time using multi-core infrastructure of CPU, by assigning one
core to each task or sub-task.

Parallelism requires hardware with multiple processing units, essentially. In single core
CPU, you may get concurrency but NOT parallelism.

Differences between concurrency vs. parallelism


Now let’s list down remarkable differences between concurrency and parallelism.
Concurrency is when two tasks can start, run, and complete in overlapping time periods.
Parallelism is when tasks literally run at the same time, eg. on a multi-core processor.

Concurrency is the composition of independently executing processes, while parallelism


is the simultaneous execution of (possibly related) computations.

Concurrency is about dealing with lots of things at once. Parallelism is about doing
lots of things at once.

An application can be concurrent – but not parallel, which means that it processes more
than one task at the same time, but no two tasks are executing at same time instant.

An application can be parallel – but not concurrent, which means that it processes
multiple sub-tasks of a task in multi-core CPU at same time.

An application can be neither parallel – nor concurrent, which means that it processes all
tasks one at a time, sequentially.

An application can be both parallel – and concurrent, which means that it processes
multiple tasks concurrently in multi-core CPU at same time .

Java Compare and Swap Example – CAS


Algorithm
By Lokesh Gupta | Filed Under: Multi Threading

One of the best additions in java 5 was Atomic operations supported in classes such
as AtomicInteger, AtomicLong etc. These classes help you in minimizing the need of
complex (un-necessary) multi-threading code for some basic operations such as
increment or decrement a value which is shared among multiple threads. These classes
internally rely on an algorithm named CAS (compare and swap). In this article, I am
going to discuss this concept in detail.

1. Optimistic and Pessimistic Locking


Traditional locking mechanisms, e.g. using synchronized keyword in java, is said to be
pessimistic technique of locking or multi-threading. It asks you to first guarantee that
no other thread will interfere in between certain operation (i.e. lock the object), and then
only allow you access to any instance/method.

It’s much like saying “please close the door first; otherwise some other crook will come
in and rearrange your stuff”.

Though above approach is safe and it does work, but it put a significant penalty on
your application in terms of performance. Reason is simple that waiting threads can
not do anything unless they also get a chance and perform the guarded operation.

There exist one more approach which is more efficient in performance, and
it optimistic in nature. In this approach, you proceed with an update, being hopeful
that you can complete it without interference. This approach relies on collision
detection to determine if there has been interference from other parties during the
update, in which case the operation fails and can be retried (or not).

The optimistic approach is like the old saying, “It is easier to obtain forgiveness than
permission”, where “easier” here means “more efficient”.

Compare and Swap is a good example of such optimistic approach, which we are going
to discuss next.

2. Compare and Swap Algorithm


This algorithm compares the contents of a memory location to a given value and, only if
they are the same, modifies the contents of that memory location to a given new value.
This is done as a single atomic operation. The atomicity guarantees that the new value is
calculated based on up-to-date information; if the value had been updated by another
thread in the meantime, the write would fail. The result of the operation must indicate
whether it performed the substitution; this can be done either with a simple Boolean
response (this variant is often called compare-and-set), or by returning the value read
from the memory location (not the value written to it).

There are 3 parameters for a CAS operation:

1. A memory location V where value has to be replaced


2. Old value A which was read by thread last time
3. New value B which should be written over V

CAS says “I think V should have the value A; if it does, put B there, otherwise don’t
change it but tell me I was wrong.” CAS is an optimistic technique—it proceeds with the
update in the hope of success, and can detect failure if another thread has updated the
variable since it was last examined.

3. Java Compare and Swap Example


Let’s understand the whole process with an example. Assume V is a memory location
where value “10” is stored. There are multiple threads who want to increment this value
and use the incremented value for other operations, a very practical scenario. Let’s break
the whole CAS operation in steps:

1) Thread 1 and 2 want to increment it, they both read the value and increment it
to 11.

V = 10, A = 0, B = 0

2) Now thread 1 comes first and compare V with it’s last read value:

V = 10, A = 10, B = 11

if A=V
V=B
else
operation failed
return V

Clearly the value of V will be overwritten as 11, i.e. operation was successful.

3) Thread 2 comes and try the same operation as thread 1

V = 11, A = 10, B = 11

if A=V
V=B
else
operation failed
return V

4) In this case, V is not equal to A, so value is not replaced and current value of V
i.e. 11 is returned. Now thread 2, again retry this operation with values:

V = 11, A = 11, B = 12
And this time, condition is met and incremented value 12 is returned to thread 2.

In summary, when multiple threads attempt to update the same variable simultaneously
using CAS, one wins and updates the variable’s value, and the rest lose. But the losers
are not punished by suspension of thread. They are free to retry the operation or simply
do nothing.

Thats all for this simple but important concept related to atomic operations supported
in java.

Happy Learning !!

Java synchronized keyword


By Lokesh Gupta | Filed Under: Multi Threading

Java synchronized keyword marks a block or method a critical section. A critical


section is where one and only one thread is executing at a time, and the thread holds
the lock for the synchronized section.

synchronized keyword helps in writing concurrent parts of the applications, to protect


shared resources within this block.

The synchronized keyword can be use with –

 a code block
 a method

1. Java synchronized block

1.1. Syntax
The general syntax for writing a synchronized block is as follows. Here lockObject is a
reference to an object whose lock associates with the monitor that the synchronized
statements represent.

synchronized( lockObject )
{
// synchronized statements
}

1.2. Internal working


When a thread wants to execute synchronized statements inside the synchronized block,
it MUST acquire the lock on lockObject‘s monitor. At a time, only one thread can
acquire the monitor of a lock object. So all other threads must wait till this thread,
currently acquired the lock, finish it’s execution.

In this way, synchronized keyword guarantees that only one thread will be executing the
synchronized block statements at a time, and thus prevent multiple threads from
corrupting the shared data inside the block.

Keep in mind that if a thread is put on sleep (using sleep() method) then it does not
release the lock. At this sleeping time, no thread will be executing the synchronized
block statements.

Java synchronization will throw NullPointerException if lock object used


in 'synchronized (lock)' is null.

1.3. Java synchronized block example


Java program to demonstrate the usage of synchronized block. In given example, we
have a MathClasswith a method printNumbers(). This method will print the numbers
starting from 1 to the argument number N.

Notice that the code in printNumbers() method is inside synchronized block.

public class MathClass


{
void printNumbers(int n) throws InterruptedException
{
synchronized (this)
{
for (int i = 1; i <= n; i++)
{
System.out.println(Thread.currentThread().getName() + " :: "+ i);
Thread.sleep(500);
}
}
}
}

I have created two threads which start executing the printNumbers() method exactly at
same time. Due to block being synchronized, only one thread is allowed access and
other thread has to wait until first thread is finished.

public class Main


{
public static void main(String args[])
{
final MathClass mathClass = new MathClass();

//first thread
Runnable r = new Runnable()
{
public void run()
{
try {
mathClass.printNumbers(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};

new Thread(r, "ONE").start();


new Thread(r, "TWO").start();
}
}

Program output.

ONE :: 1
ONE :: 2
ONE :: 3

TWO :: 1
TWO :: 2
TWO :: 3

2. Java synchronized method


2.1. Syntax
The general syntax for writing a synchronized method is as follows. Here lockObject is a
reference to an object whose lock associates with the monitor that the synchronized
statements represent.

<access modifier> synchronized method( parameters )


{
// synchronized code
}

2.2. Internal working


Similar to synchronized block, a thread MUST acquire the lock on the associated
monitor object with synchronized method. In case of synchronized method, the lock
object is –

 ‘.class’ object – if the method is static.


 ‘this’ object – if the method is not static. ‘this’ refer to reference to current object
in which synchronized method is invoked.

Read More : Object level lock vs Class level lock in Java

Java synchronized keyword is re-entrant in nature it means if a synchronized method


calls another synchronized method which requires same lock then current thread which
is holding lock can enter into that method without acquiring lock.

2.3. Java synchronized method example


Similar to synchronized block example, we can apply synchronized keyword
at printNumber() method and it will make the method as synchronized. Now if we again
run the example, we will get the similar output.

public class MathClass


{
synchronized void printNumbers(int n) throws InterruptedException
{
for (int i = 1; i <= n; i++)
{
System.out.println(Thread.currentThread().getName() + " :: "+ i);
Thread.sleep(500);
}
}
}

Program output.

ONE :: 1
ONE :: 2
ONE :: 3

TWO :: 1
TWO :: 2
TWO :: 3

Drop me your questions in comments.

Happy Learning !!

Object level lock vs Class level lock in Java


By Lokesh Gupta | Filed Under: Multi Threading

In Java, a synchronized block of code can only be executed by one thread at a time.
Also, java supports multiple threads to be executed concurrently. This may cause two or
more threads to access the same fields or objects at same time.

Synchronization is the process which keeps all concurrent threads in execution to be in


sync. Synchronization avoids memory consistence errors caused due to inconsistent
view of shared memory. When a method is declared as synchronized; the thread holds
the monitor or lock object for that method’s object. If another thread is executing
the synchronized method, your thread is blocked until that thread releases the monitor.

Please note that we can use synchronized keyword in the class on defined methods or
blocks. synchronized keyword can not be used with variables or attributes in class
definition.

1. Object level lock in Java


Object level lock is mechanism when we want to synchronize a non-static
method or non-static code block such that only one thread will be able to execute the
code block on given instance of the class. This should always be done to make instance
level data thread safe.

Object level locking can be done as below :

Various ways for object level locking


public class DemoClass
{
public synchronized void demoMethod(){}
}

or

public class DemoClass


{
public void demoMethod(){
synchronized (this)
{
//other thread safe code
}
}
}

or

public class DemoClass


{
private final Object lock = new Object();
public void demoMethod(){
synchronized (lock)
{
//other thread safe code
}
}
}

2. Class level lock in Java


Class level lock prevents multiple threads to enter in synchronized block in any of all
available instances of the class on runtime. This means if in runtime there are 100
instances of DemoClass, then only one thread will be able to execute demoMethod() in any
one of instance at a time, and all other instances will be locked for other threads.
Class level locking should always be done to make static data thread safe. As we know
that statickeyword associate data of methods to class level, so use locking at static
fields or methods to make it on class level.

Various ways for class level locking


public class DemoClass
{
//Method is static
public synchronized static void demoMethod(){

}
}

or

public class DemoClass


{
public void demoMethod()
{
//Acquire lock on .class reference
synchronized (DemoClass.class)
{
//other thread safe code
}
}
}

or

public class DemoClass


{
private final static Object lock = new Object();

public void demoMethod()


{
//Lock object is static
synchronized (lock)
{
//other thread safe code
}
}
}

3. Object level lock vs class level lock – Important notes


1. Synchronization in Java guarantees that no two threads can execute a
synchronized method, which requires same lock, simultaneously or concurrently.
2. synchronized keyword can be used only with methods and code blocks. These
methods or blocks can be static or non-static both.
3. When ever a thread enters into Java synchronized method or block it acquires a
lock and whenever it leaves synchronized method or block it releases the lock.
Lock is released even if thread leaves synchronized method after completion or
due to any Error or Exception.
4. Java synchronized keyword is re-entrant in nature it means if a synchronized
method calls another synchronized method which requires same lock then current
thread which is holding lock can enter into that method without acquiring lock.
5. Java synchronization will throw NullPointerException if object used in
synchronized block is null. For example, in above code sample if lock is initialized
as null, the “synchronized (lock)” will throw NullPointerException.
6. Synchronized methods in Java put a performance cost on your application. So use
synchronization when it is absolutely required. Also, consider using synchronized
code blocks for synchronizing only critical section of your code.
7. It’s possible that both static synchronized and non static synchronized method can
run simultaneously or concurrently because they lock on different object.
8. According to the Java language specification you can not
use synchronized keyword with constructor. It is illegal and result in compilation
error.
9. Do not synchronize on non final field on synchronized block in Java. because
reference of non final field may change any time and then different thread might
synchronizing on different objects i.e. no synchronization at all.
10. Do not use String literals because they might be referenced else where in the
application and can cause deadlock. String objects created with new keyword can
be used safely. But as a best practice, create a new private scoped Object instance
OR lock on the shared variable itself which we want to protect. [Thanks to Anu to
point this out in comments.]

Let me know thoughts and queries on Object level lock vs Class level lock in Java.

Happy Learning !!

Difference between Runnable vs Thread in


Java
By Lokesh Gupta | Filed Under: Multi Threading

In java language, as we all know that there are two ways to create threads. One
using Runnableinterface and another by extending Thread class. Let’s identify the
differences between both ways i.e extends thread and implements runnable.

1. Create Thread using Runnable Interface vs Thread


class
Let’s quickly check the java code of usage of both techniques.

1.1. Runnable interface


Java program to create thread by implementing Runnable interface.

public class DemoRunnable implements Runnable {


public void run() {
//Code
}
}

//start new thread with a "new Thread(new demoRunnable()).start()" call

1.2. Thread class


Java program to create thread by extending Thread class.

public class DemoThread extends Thread {


public DemoThread() {
super("DemoThread");
}
public void run() {
//Code
}
}
//start new thread with a "new demoThread().start()" call

2. Difference between Runnable vs Thread


There has been a good amount of debate on which is better way. Well, I also tried to
find out and below is my learning.
1. Implementing Runnable is the preferred way to do it. Here, you’re not really
specializing or modifying the thread’s behavior. You’re just giving the thread
something to run. That means composition is the better way to go.
2. Java only supports single inheritance, so you can only extend one class.
3. Instantiating an interface gives a cleaner separation between your code and the
implementation of threads.
4. Implementing Runnable makes your class more flexible. If you extend Thread then
the action you’re doing is always going to be in a thread. However, if you
implement Runnable it doesn’t have to be. You can run it in a thread, or pass it to
some kind of executor service, or just pass it around as a task within a single
threaded application.
5. If you are working on JDK 4 or lesser, then there is bug :

http://bugs.java.com/bugdatabase/view_bug.do;jsessionid=5869e03fee226ffffffffc
40d4fa881a86e3:WuuT?bug_id=4533087

It’s fixed in Java 1.5 but Sun doesn’t intend to fix it in 1.4.

The issue is that at construction time, a Thread is added to a list of references in an


internal thread table. It won’t get removed from that list until its start() method
has completed. As long as that reference is there, it won’t get garbage collected.

That’s all about differences between Runnable interface and Thread class in java. If
you know something more, please put that in comments section and I will include in
post content.

Happy Learning !!

Difference between lock and monitor – Java


Concurrency
By Lokesh Gupta | Filed Under: Multi Threading

You may have faced this question in your interview that what is the difference between
lock and a monitor? Well, to answer this question you must have good amount of
understanding of how java multi-threading works under the hood.
Short answer, locks provide necessary support for implementing monitors. Long answer
read below.

Locks
A lock is kind of data which is logically part of an object’s header on the heap
memory. Each object in a JVM has this lock (or mutex) that any program can use to
coordinate multi-threaded access to the object. If any thread want to access instance
variables of that object; then thread must “own” the object’s lock (set some flag in lock
memory area). All other threads that attempt to access the object’s variables have to
wait until the owning thread releases the object’s lock (unset the flag).

Once a thread owns a lock, it can request the same lock again multiple times, but then
has to release the lock the same number of times before it is made available to other
threads. If a thread requests a lock three times, for example, that thread will continue to
own the lock until it has “released” it three times.

Please note that lock is acquired by a thread, when it explicitly ask for it. In Java, this is
done with the synchronized keyword, or with wait and notify.

Monitors
Monitor is a synchronization construct that allows threads to have both mutual
exclusion (using locks) and cooperation i.e. the ability to make threads wait for
certain condition to be true (using wait-set).

In other words, along with data that implements a lock, every Java object is logically
associated with data that implements a wait-set. Whereas locks help threads to work
independently on shared data without interfering with one another, wait-sets help
threads to cooperate with one another to work together towards a common goal e.g. all
waiting threads will be moved to this wait-set and all will be notified once lock is
released. This wait-set helps in building monitors with additional help of lock
(mutex).

Mutual exclusion
Putting in very simple words, a monitor is like a building that contains one special room
(object instance) that can be occupied by only one thread at a time. The room usually
contains some data which needs to be protected from concurrent access. From the time
a thread enters this room to the time it leaves, it has exclusive access to any data in the
room. Entering the monitor building is called “entering the monitor.” Entering the
special room inside the building is called “acquiring the monitor.” Occupying the room
is called “owning the monitor,” and leaving the room is called “releasing the monitor.”
Leaving the entire building is called “exiting the monitor.”

When a thread arrives to access protected data (enter the special room), it is first put in
queue in building reception (entry-set). If no other thread is waiting (own the monitor),
the thread acquires the lock and continues executing the protected code. When the
thread finishes execution, it release the lock and exits the building (exiting the monitor).

If when a thread arrives and another thread is already owning the monitor, it must wait
in reception queue (entry-set). When the current owner exits the monitor, the newly
arrived thread must compete with any other threads also waiting in the entry-set. Only
one thread will win the competition and own the lock.

There is no role of wait-set feature.

Cooperation
In general, mutual exclusion is important only when multiple threads are sharing data or
some other resource. If two threads are not working with any common data or resource,
they usually can’t interfere with each other and needn’t execute in a mutually exclusive
way. Whereas mutual exclusion helps keep threads from interfering with one another
while sharing data, cooperation helps threads to work together towards some common
goal.

Cooperation is important when one thread needs some data to be in a particular


state and another thread is responsible for getting the data into that state e.g.
producer/consumer problem where read thread needs the buffer to be in a “not
empty” state before it can read any data out of the buffer. If the read thread discovers
that the buffer is empty, it must wait. The write thread is responsible for filling the buffer
with data. Once the write thread has done some more writing, the read thread can do
some more reading. It is also sometimes called a “Wait and Notify” OR “Signal and
Continue” monitor because it retains ownership of the monitor and continues executing
the monitor region (the continue) if needed. At some later time, the notifying thread
releases the monitor and a waiting thread is resurrected to own the lock.

This cooperation requires both i.e. entry-set and wait-set. Below given diagram will
help you in understand this cooperation.
Above figure shows the monitor as three rectangles. In the center, a large rectangle
contains a single thread, the monitor’s owner. On the left, a small rectangle contains the
entry set. On the right, another small rectangle contains the wait set.

I hope that above discussion will help you in getting more insight. Free free to ask any
question.

Happy Learning !!

Java Callable Future Example


By Lokesh Gupta | Filed Under: Multi Threading

One of the benefits of the Java executor framework is that we can run concurrent tasks
that may return a single result after processing the tasks. The Java Concurrency API
achieves this with the following two interfaces Callable and Future.

1. Java Callable and Future interfaces

1.1. Callable
Callable interface has the call() method. In this method, we have to implement the
logic of a task. The Callable interface is a parameterized interface, meaning we have to
indicate the type of data the call() method will return.

2.2. Future
Future interface has methods to obtain the result generated by a Callable object and to
manage its state.

2. Java Callable Future Example


In this example, We are creating a FactorialCalculator which is of type Callable. It
means we will override it’s call() method and after calculation, we will return the result
from call() method. This result later can be retrieved from Future reference held by
main program.

FactorialCalculator.java
public class FactorialCalculator implements Callable<Integer>
{

private Integer number;

public FactorialCalculator(Integer number) {


this.number = number;
}

@Override
public Integer call() throws Exception {
int result = 1;
if ((number == 0) || (number == 1)) {
result = 1;
} else {
for (int i = 2; i <= number; i++) {
result *= i;
TimeUnit.MILLISECONDS.sleep(20);
}
}
System.out.println("Result for number - " + number + " -> " + result);
return result;
}
}

Now let’s test the above factorial calculator using two threads and 4 numbers.

CallableExample.java
package com.howtodoinjava.demo.multithreading;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class CallableExample


{
public static void main(String[] args)
{
ThreadPoolExecutor executor = (ThreadPoolExecutor)
Executors.newFixedThreadPool(2);

List<Future<Integer>> resultList = new ArrayList<>();

Random random = new Random();

for (int i=0; i<4; i++)


{
Integer number = random.nextInt(10);
FactorialCalculator calculator = new FactorialCalculator(number);
Future<Integer> result = executor.submit(calculator);
resultList.add(result);
}

for(Future<Integer> future : resultList)


{
try
{
System.out.println("Future result is - " + " - " + future.get() + ";
And Task done is " + future.isDone());
}
catch (InterruptedException | ExecutionException e)
{
e.printStackTrace();
}
}
//shut down the executor service now
executor.shutdown();
}
}

Program output.
Console
Result for number - 4 -> 24
Result for number - 6 -> 720
Future result is - - 720; And Task done is true
Future result is - - 24; And Task done is true
Result for number - 2 -> 2
Result for number - 6 -> 720
Future result is - - 720; And Task done is true
Future result is - - 2; And Task done is true

Here we sent a Callable object to be executed in an executor using


the submit() method. This method receives a Callable object as a parameter and
returns a Future object that we can use with two main objectives –

1. We can control the status of the task – we can cancel the task and check if it has
finished. For this purpose, we have used the isDone() method to check if the tasks
had finished.
2. We can get the result returned by the call() method. For this purpose, we have
used the get()method. This method waits until the Callable object has finished
the execution of the call()method and has returned its result.

If the thread is interrupted while the get() method is waiting for the result, it
throws an InterruptedException exception. If the call() method throws an
exception, this method throws an ExecutionException exception.

The Future interface provides another version of the get() method


i.e. get(longtimeout,TimeUnitunit). This version of the get method, if the result of the
task isn’t available, waits for it for the specified time. If the specified period of time
passes and the result isn’t yet available, the method returns a null value.

Happy Learning !!

How to Restart Thread Using


UncaughtExceptionHandler
By Lokesh Gupta | Filed Under: Multi Threading

As we are already aware that there are two kinds of exceptions in Java. Checked
exceptions and Unchecked exceptions. Checked exceptions must be specified in the
throws clause of a method or caught inside them. Unchecked exceptions don’t have to
be specified or caught. When a checked exception is thrown inside the run() method of
a Thread object, we have to catch and treat it accordingly, because the run() method
doesn’t accept a throws clause. But when an unchecked exception is thrown inside
the run() method of a Thread object, the default behavior is to write the stack trace in
the console (or log it inside error log file) and exit the program.

Fortunately, Java provides us with a mechanism to catch and treat the unchecked
exceptions thrown in a Thread object to avoid the program ending. This can be done
using UncaughtExceptionHandler.

Let’s take an example of UncaughtExceptionHandler usage. In this example, we have


created a thread which tries to parse few strings which are supposed to be integers. We
have written the run() method such that it throws a “java.lang.NumberFormatException”
during it’s execution. As program does not try to catch this exception, exception floats
through JVM level and thread gets killed. This is absolutely normal behavior but it MAY
NOT be desired behavior.

Without Using UncaughtExceptionHandler


In real life application, you would like to try more than once to perform a critical task
even if it failed couple of times. Our example below demonstrate the usecase, first
without use of UncaughtExceptionHandler; which causes the thread to die immediately
after failure.

Task.java

class Task implements Runnable

@Override

public void run()

System.out.println(Integer.parseInt("123"));

System.out.println(Integer.parseInt("234"));

System.out.println(Integer.parseInt("345"));

System.out.println(Integer.parseInt("XYZ")); //This will cause NumberFormatException

System.out.println(Integer.parseInt("456"));

}
}

DemoThreadExample.java

public class DemoThreadExample

public static void main(String[] args)

Task task = new Task();

Thread thread = new Thread(task);

thread.start();

Below is output we get when we run the thread:

123
234
345
Exception in thread "Thread-0" java.lang.NumberFormatException: For input string: "XYZ"
at java.lang.NumberFormatException.forInputString(Unknown Source)
at java.lang.Integer.parseInt(Unknown Source)
at java.lang.Integer.parseInt(Unknown Source)
at examples.algorithms.sleepingbarber.Task.run(DemoThreadExample.java:24)
at java.lang.Thread.run(Unknown Source)

After Using UncaughtExceptionHandler


Let’s add one UncaughtExceptionHandler implementation to catch any unchecked
exception during runtime.

ExceptionHandler.java

class ExceptionHandler implements UncaughtExceptionHandler

public void uncaughtException(Thread t, Throwable e)

{
System.out.printf("An exception has been captured\n");

System.out.printf("Thread: %s\n", t.getId());

System.out.printf("Exception: %s: %s\n", e.getClass().getName(), e.getMessage());

System.out.printf("Stack Trace: \n");

e.printStackTrace(System.out);

System.out.printf("Thread status: %s\n", t.getState());

new Thread(new Task()).start();

Now add this exception handler to the thread.

class Task implements Runnable

@Override

public void run()

Thread.currentThread().setUncaughtExceptionHandler(new ExceptionHandler());

System.out.println(Integer.parseInt("123"));

System.out.println(Integer.parseInt("234"));

System.out.println(Integer.parseInt("345"));

System.out.println(Integer.parseInt("XYZ")); //This will cause NumberFormatException

System.out.println(Integer.parseInt("456"));

Now run the above example once again. This will run continuously. In real life, if this task
is able to complete it’s task then it will exit without throwing any exception and will
complete it’s life cycle.

123
234
345
An exception has been captured
Thread: 1394
Exception: java.lang.NumberFormatException: For input string: "XYZ"
Stack Trace:
java.lang.NumberFormatException: For input string: "XYZ"
at java.lang.NumberFormatException.forInputString(Unknown Source)
at java.lang.Integer.parseInt(Unknown Source)
at java.lang.Integer.parseInt(Unknown Source)
at examples.algorithms.sleepingbarber.Task.run(DemoThreadExample.java:24)
at java.lang.Thread.run(Unknown Source)
Thread status: RUNNABLE
123
234
345
An exception has been captured
Thread: 1395
Exception: java.lang.NumberFormatException: For input string: "XYZ"
Stack Trace:
java.lang.NumberFormatException: For input string: "XYZ"
at java.lang.NumberFormatException.forInputString(Unknown Source)
at java.lang.Integer.parseInt(Unknown Source)
at java.lang.Integer.parseInt(Unknown Source)
at examples.algorithms.sleepingbarber.Task.run(DemoThreadExample.java:24)
at java.lang.Thread.run(Unknown Source)
Thread status: RUNNABLE
123
234
345

Above implementation helps you to run a thread in a way such that it will run until it’s task is
done. This can be achieved though other multi-threading concepts as well.

Please note that UncaughtExceptionHandler can be used for making logging more
robust only as well without restarting the thread, because often default logs
doesn’t provide enough information about the context when thread execution
failed.

Happy Learning !!

Throttling Task Submission Rate with


ThreadPoolExecutor and Semaphore
By Lokesh Gupta | Filed Under: Multi Threading

If you may know that in web-servers you can configure the maximum number of
concurrent connections to the server. If more connections than this limit come to server,
they have to wait until some other connections are freed or closed. This limitation can
be taken as throttling. Throttling is the capability of regulating the rate of input for a
system where output rate is slower than input. It is necessary to stop the system from
crashing or resource exhaustion.

In one of my previous post related to BlockingQueue and ThreadPoolExecutor, We


learned about creating a CustomThreadPoolExecutor which had following capabilities:

1) Tasks being submitted to blocking queue


2) An executor which picks up the task from queue and execute them
3) Had overridden beforeExecute() and afterExecute() methods to perform some extra
activities if needed
4) Attached a RejectedExecutionHandler which handle the task if it got rejected because
the queue was full

Our approach was good enough already and capable of handling most of the practical
scenarios. Now let’s add one more concept into it which may prove beneficial in some
conditions. This concept is around throttling of task submission in queue.

In this example, throttling will help in keeping the number of tasks in queue in limit so that no
task get rejected. It essentially removes the necessity of RejectedExecutionHandler as well.

Previous Solution Using CustomThreadPoolExecutor


with RejectedExecutionHandler
In this solution, we had following classes:

DemoTask.java

public class DemoTask implements Runnable

private String name = null;

public DemoTask(String name) {

this.name = name;

public String getName() {


return this.name;

@Override

public void run(){

try {

Thread.sleep(1000);

} catch (InterruptedException e){

e.printStackTrace();

System.out.println("Executing : " + name);

CustomThreadPoolExecutor.java

import java.util.concurrent.BlockingQueue;

import java.util.concurrent.ThreadPoolExecutor;

import java.util.concurrent.TimeUnit;

public class CustomThreadPoolExecutor extends ThreadPoolExecutor

public CustomThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime,

TimeUnit unit, BlockingQueue<Runnable> workQueue)

super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);

@Override

protected void beforeExecute(Thread t, Runnable r)

{
super.beforeExecute(t, r);

@Override

protected void afterExecute(Runnable r, Throwable t)

super.afterExecute(r, t);

if (t != null)

t.printStackTrace();

DemoExecutor.java

import java.util.concurrent.ArrayBlockingQueue;

import java.util.concurrent.BlockingQueue;

import java.util.concurrent.RejectedExecutionHandler;

import java.util.concurrent.ThreadPoolExecutor;

import java.util.concurrent.TimeUnit;

public class DemoExecutor

public static void main(String[] args)

Integer threadCounter = 0;

BlockingQueue<Runnable> blockingQueue = new ArrayBlockingQueue<Runnable>(50);

CustomThreadPoolExecutor executor = new CustomThreadPoolExecutor(10, 20, 5000,


TimeUnit.MILLISECONDS, blockingQueue);

executor.setRejectedExecutionHandler(new RejectedExecutionHandler()

{
@Override

public void rejectedExecution(Runnable r, ThreadPoolExecutor executor)

System.out.println("DemoTask Rejected : " + ((DemoTask) r).getName());

try

Thread.sleep(1000);

} catch (InterruptedException e)

e.printStackTrace();

System.out.println("Lets add another time : " + ((DemoTask) r).getName());

executor.execute(r);

});

// Let start all core threads initially

executor.prestartAllCoreThreads();

while (true)

threadCounter++;

// Adding threads one by one

//System.out.println("Adding DemoTask : " + threadCounter);

executor.execute(new DemoTask(threadCounter.toString()));

if (threadCounter == 1000)

break;

If we run the above program, we will get the output like below:
DemoTask Rejected : 71
Executing : 3

Executing : 5

...

...

There will be multiple occurrences of “DemoTask Rejected“. In next solution, we will put
throttle technique so that no task should be rejected.

Throttling Task submission rate using


ThreadPoolExecutor and Semaphore
In this solution, we will create a Semaphore with a number which must be equal to
maximum number of tasks in blocking queue at any given point of time. So the
approach works like this:

1) Before executing a task a lock in semaphore is requested


2) If lock is acquired then execution works normally; Otherwise retry will happen until
lock is acquired
3) Once task is completed; lock is released to semaphore

Our new throttling enabled BlockingThreadPoolExecutor looks like below:

package threadpoolDemo;

import java.util.concurrent.BlockingQueue;

import java.util.concurrent.RejectedExecutionException;

import java.util.concurrent.Semaphore;

import java.util.concurrent.ThreadPoolExecutor;

import java.util.concurrent.TimeUnit;

public class BlockingThreadPoolExecutor extends ThreadPoolExecutor

private final Semaphore semaphore;


public BlockingThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTim
TimeUnit unit, BlockingQueue<Runnable> workQueue)

super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);

semaphore = new Semaphore(corePoolSize + 50);

@Override

protected void beforeExecute(Thread t, Runnable r)

super.beforeExecute(t, r);

@Override

public void execute(final Runnable task)

boolean acquired = false;

do

try

semaphore.acquire();

acquired = true;

} catch (final InterruptedException e)

//LOGGER.warn("InterruptedException whilst aquiring semaphore", e);

} while (!acquired);

try

super.execute(task);
} catch (final RejectedExecutionException e)

System.out.println("Task Rejected");

semaphore.release();

throw e;

@Override

protected void afterExecute(Runnable r, Throwable t)

super.afterExecute(r, t);

if (t != null)

t.printStackTrace();

semaphore.release();

Now test the code as below.

package threadpoolDemo;

import java.util.concurrent.ArrayBlockingQueue;

import java.util.concurrent.BlockingQueue;

import java.util.concurrent.RejectedExecutionHandler;

import java.util.concurrent.ThreadPoolExecutor;

import java.util.concurrent.TimeUnit;

public class DemoExecutor


{

public static void main(String[] args)

Integer threadCounter = 0;

BlockingQueue<Runnable> blockingQueue = new ArrayBlockingQueue<Runnable>(50);

BlockingThreadPoolExecutor executor = new BlockingThreadPoolExecutor(10, 20, 5000,


TimeUnit.MILLISECONDS, blockingQueue);

executor.setRejectedExecutionHandler(new RejectedExecutionHandler()

@Override

public void rejectedExecution(Runnable r, ThreadPoolExecutor executor)

System.out.println("DemoTask Rejected : " + ((DemoTask) r).getName());

try

Thread.sleep(1000);

} catch (InterruptedException e)

e.printStackTrace();

System.out.println("Lets add another time : " + ((DemoTask) r).getName());

executor.execute(r);

});

// Let start all core threads initially

executor.prestartAllCoreThreads();

while (true)

threadCounter++;

// Adding threads one by one

System.out.println("Adding DemoTask : " + threadCounter);


executor.execute(new DemoTask(threadCounter.toString()));

if (threadCounter == 1000)

break;

When you run the DemoExecutor program using BlockingThreadPoolExecutor in place


of CustomThreadPoolExecutor, you will not see any task rejected and all tasks will be
executed successfully.

Java Inter-thread Communication –


PipedReader and PipedWriter
By Lokesh Gupta | Filed Under: Multi Threading

Java inter-thread communication has been a popular interview question for a long time.
With the JDK 1.5 release, ExecutorService and BlockingQueue brought another way of
doing it more effectively, but piped stream approach is also worth knowing and might
be useful in certain scenarios.

Table of contents

What are piped streams


PipedReader and PipedWriter
Java inter-thread communication example
Summary

What are piped streams


Pipe streams are just like real plumbing pipes. You put things into to a pipe at one end
– using some methods. Then you receive the same things back from the pipe stream at
the other end – using some other methods.

They come out in FIFO order, first-in first-out, just like from real plumbing pipes.
PipedReader and PipedWriter
PipedReader is an extension of Reader class which is used for reading character
streams. Its read() method reads the connected PipedWriter’s stream.
Similarly, PipedWriter is an extension of Writer class and does all the things which
Reader class contracts.

A writer can be connected to a reader by following two methods:

1. Using constructor PipedWriter(PipedReader pr)


2. Using connect(PipedReader pr) method

Once connected through any of above ways, any thread can write data in stream
using write(....)methods, and data will be available to reader and can be read
using read() method.

Java inter-thread communication example


Below given Java program creates two threads. One thread is responsible for writing
into stream and second one is only reading the data to print them in console.

public class PipeReaderThread implements Runnable


{
PipedReader pr;
String name = null;

public PipeReaderThread(String name, PipedReader pr)


{
this.name = name;
this.pr = pr;
}

public void run()


{
try {
// continuously read data from stream and print it in console
while (true) {
char c = (char) pr.read(); // read a char
if (c != -1) { // check for -1 indicating end of file
System.out.print(c);
}
}
} catch (Exception e) {
System.out.println(" PipeThread Exception: " + e);
}
}
}
public class PipeWriterThread implements Runnable
{
PipedWriter pw;
String name = null;

public PipeWriterThread(String name, PipedWriter pw) {


this.name = name;
this.pw = pw;
}

public void run() {


try {
while (true) {
// Write some data after every two seconds
pw.write("Testing data written...n");
pw.flush();
Thread.sleep(2000);
}
} catch (Exception e) {
System.out.println(" PipeThread Exception: " + e);
}
}
}
package multiThread;

import java.io.*;

public class PipedCommunicationTest


{
public static void main(String[] args)
{
new PipedCommunicationTest();
}

public PipedCommunicationTest()
{
try
{
// Create writer and reader instances
PipedReader pr = new PipedReader();
PipedWriter pw = new PipedWriter();

// Connect the writer with reader


pw.connect(pr);
// Create one writer thread and one reader thread
Thread thread1 = new Thread(new PipeReaderThread("ReaderThread", pr));

Thread thread2 = new Thread(new PipeWriterThread("WriterThread", pw));

// start both threads


thread1.start();
thread2.start();

}
catch (Exception e)
{
System.out.println("PipeThread Exception: " + e);
}
}
}

Program Output:

Testing data written...


Testing data written...
Testing data written...

Summary
 You cannot write to a pipe without having some sort of reader created and
connected to it. In other words, both ends must be present and already connected
for the writing end to work.
 You cannot switch to another reader, to which the pipe was not originally
connected, once you are done writing to a pipe.
 You cannot read back from the pipe if you close the reader. You can close the
writing end successfully, however, and still read from the pipe.
 You cannot read back from the pipe if the thread which wrote to it ends.

Java Deadlock Example and Solution


By Lokesh Gupta | Filed Under: Multi Threading
Learn to create a deadlock in Java, programmatically, with an example. Also learn
to detect deadlockand how to solve a deadlock situation in sourcecode.

In my previous post, I written about auto reload of configuration when any change
happen in property files, I discussed about refreshing your application configuration
using Java WatchService. As configurations are shared resources and when accessing
via Threads, there is always chance of writing incorrect code which can cause in
deadlock situation.

1. Deadlock
In Java, a deadlock is a situation where minimum two threads are holding the lock on
some different resource, and both are waiting for other’s resource to complete its task.
And, none is able to leave the lock on the resource it is holding.

Deadlock Scenario

In above case, Thread-1 has A but need B to complete processing and similarly Thread-
2 has resource Bbut need A first.

ResolveDeadLockTest.java

package thread;

public class ResolveDeadLockTest {

public static void main(String[] args) {

ResolveDeadLockTest test = new ResolveDeadLockTest();

final A a = test.new A();


final B b = test.new B();

// Thread-1

Runnable block1 = new Runnable() {

public void run() {

synchronized (a) {

try {

// Adding delay so that both threads can start trying to

// lock resources

Thread.sleep(100);

} catch (InterruptedException e) {

e.printStackTrace();

// Thread-1 have A but need B also

synchronized (b) {

System.out.println("In block 1");

};

// Thread-2

Runnable block2 = new Runnable() {

public void run() {

synchronized (b) {

// Thread-2 have B but need A also

synchronized (a) {

System.out.println("In block 2");

}
}

};

new Thread(block1).start();

new Thread(block2).start();

// Resource A

private class A {

private int i = 10;

public int getI() {

return i;

public void setI(int i) {

this.i = i;

// Resource B

private class B {

private int i = 20;

public int getI() {

return i;

public void setI(int i) {


this.i = i;

Running above code will result in a deadlock for very obvious reasons (explained above).
Now we have to solve this issue.

2. How to avoid deadlock


I believe, the solution to any problem lies in identifying the root of the problem. In our
case, it is the pattern of accessing the resources A and B, is main issue. So, to solve it, we
will simply re-order the statements where the code is accessing shared resources.

ResolveDeadLockTest.java
// Thread-1

Runnable block1 = new Runnable() {

public void run() {

synchronized (b) {

try {

// Adding delay so that both threads can start trying to

// lock resources

Thread.sleep(100);

} catch (InterruptedException e) {

e.printStackTrace();

// Thread-1 have A but need B also

synchronized (a) {

System.out.println("In block 1");

};
// Thread-2

Runnable block2 = new Runnable() {

public void run() {

synchronized (b) {

// Thread-2 have B but need A also

synchronized (a) {

System.out.println("In block 2");

};

Run again above class, and you will not see any deadlock kind of situation. I hope, it will
help you in avoiding deadlocks, and if encountered, in resolving them.

You might also like