MultiThreading and Executor
MultiThreading and Executor
Thread can block due to IO operation (http, db, file read write), locks, latches etc
Uninterruptible operations are typically non-blocking operations, such as reading from a memory
location or writing to a file. When an uninterruptible operation is interrupted, the thread that is
performing the operation does not throw an exception. However, the operation may be
unsuccessful.
Stop thread after certain time - Interrupt
https://www.baeldung.com/java-stop-execution-after-certain-time
Thread.stop
Stopping the thread causes it to unlock all of the monitors that it has locked. This happens because
of the ThreadDeath exception that propagates up the stack.
If any of the objects previously protected by these monitors were in an inconsistent state, the
inconsistent objects become visible to other threads. This can lead to arbitrary behavior that is very
hard to detect and reason about.
Interrupting a thread
There is no cancel method on thread. It’s a cooperative mechanism to stop the thread. It can only be
interrupted. It may or may not stop on interrupt. On calling interrupt it sets the isInterrupted flag to
true but we need to implement to check in the interrupted thread task if it’s interrupted then stop
Thread.interrupted() -> get the current status if thread is interrupted then it will return true and
then it will be reset. To set interrupted flag again call Thread.currentThread.interrupt(); in the catch
block. if a thread is interrupted and a flag is set, nothing else will happen until it reaches one of these
interruptible methods.
A thread that is in “waiting” state to acquire the access to synchronized block can’t be interrupted
https://stackoverflow.com/questions/17141003/why-does-threads-in-blocked-state-do-not-get-
interrupted
https://stackoverflow.com/questions/18702482/ensure-that-a-task-is-interruptible
Thread lock
https://www.baeldung.com/java-concurrent-locks#:~:text=boolean%20tryLock(long%20timeout%2C
%20TimeUnit,()%20unlocks%20the%20Lock%20instance.
Lock vs synchronized
Synchronized is implicit and locks are explicit as custom lock needs to be created. For synchronized
locks are within the same scope from starting brace to ending brace. But lock can be unlocked in
different scopes. Ideally lock should be unlocked in finally block
Synchronized
Synchronized blocks use re-entrant locks, which means if the thread already holds the lock, it can re-
acquire it without problems. a thread cannot acquire a lock owned by another thread. But a thread
can acquire a lock that it already owns. Allowing a thread to acquire the same lock more than once
enables re-entrant synchronization.
Synchronizing run()
1. The run() method is not meant to be synchronized - The run() method is a public method that is
called by the Thread class to execute the thread. Synchronizing the run() method would prevent
multiple threads from executing the same instance of the class at the same time, which could lead to
performance issues.
2. It is not necessary - In most cases, there is no need to synchronize the run() method. If you need
to synchronize access to shared data, you can do so by synchronizing the methods that access the
data, rather than synchronizing the run() method.
1. Use a synchronized block - If you need to synchronize access to a specific section of code, you can
use a synchronized block. This will prevent multiple threads from executing the code in the block at
the same time.
2. Use a lock object - If you need to synchronize access to a shared object, you can use a lock object.
This will prevent multiple threads from accessing the object at the same time.
3. Use a concurrent data structure - If you need to share data between threads, you can use a
concurrent data structure. Concurrent data structures are designed to be accessed by multiple
threads safely.
InterruptedException
InterruptedException needs to be thrown to inform the main thread that on interruption the thread
is being stopped. Thread.sleep, Object.wait will throw interrupted exception if thread.interrupt is
called on sleeping or waiting thread
https://stackoverflow.com/questions/3976344/handling-interruptedexception-in-java
IllegalStateException
start() method on a thread can only be called once. If you try to call it twice, it will throw an
IllegalThreadStateException. This is because once the thread's run() method has been executed, the
thread is considered to be in a "dead" state and cannot be restarted.
RejectionExecutionException
If shutdown is invoked on an executor service, it will complete all the tasks which are already
submitted but new tasks are submitted again after shutdown will throw
RejectionExecutionException.
Execution exception
If future.get() throws an exception propogated from executing the task submitted to executor
service, this will be wrapped in an ExecutionException so future.get() should catch
ExecutionException
Do threads share common memory?
https://stackoverflow.com/questions/1762418/what-resources-are-shared-between-threads
https://stackoverflow.com/questions/3318750/why-do-threads-share-the-heap-space
https://stackoverflow.com/questions/76862157/memory-sharing-between-threads
Join
Calling Thread.join makes the calling thread wait for the thread to finish executing. That means it will
get "blocked" on that statement and won't continue until it's done executing. Passing an argument
lets you specify a timeout, which means the calling thread will wait until the thread finishes, or give
up when the timeout passes.
In your code obj.join(500) makes your main thread do nothing and wait until the obj thread to finish,
or until 500 milliseconds passes, whichever one happens first.
https://stackoverflow.com/questions/15956231/what-does-this-thread-join-code-mean
yield() basically means that the thread is not doing anything particularly important and if any other
threads or processes need to be run, they should. Otherwise, the current thread will continue to run.
Yield like sleep does not release a lock. The yield() gives a hint that the current thread is willing to
yield its current use of a processor. The thread scheduler may or may not choose to switch to
another thread, depending on the scheduling algorithm in use.
https://stackoverflow.com/questions/6979796/what-are-the-main-uses-of-yield-and-how-does-it-
differ-from-join-and-interr
https://stackoverflow.com/questions/66183005/is-thread-yield-same-as-non-blocking-io-in-java
Object.wait
The wait() method in Java is used to temporarily suspend the execution of a thread. When a thread
calls wait() on an object, it releases the lock on the object and waits until another thread calls
notify() or notifyAll() on the same object. The thread then waits until it can re-obtain ownership of
the monitor and resumes execution.
The wait() method can be called only within a synchronized block. If the thread is not the owner of
the monitor of the object on which it calls wait(), an IllegalMonitorStateException is thrown.
wait(): This method causes the current thread to wait indefinitely until another thread
invokes the notify() method or the notifyAll() method for this object.
wait(long timeout): This method causes the current thread to wait until another thread
invokes the notify() method or the notifyAll() method for this object, or until the specified
timeout expires. If the timeout expires, the current thread will resume execution.
wait is interruptible. Thus, the thread blocked in the wait method will immediately throw an
InterruptedException after the interrupt flag is set.
https://www.baeldung.com/java-wait-notify#:~:text=wait(long%20timeout),same%20as%20calling
%20wait().
Wait vs sleep
Sleep will not release lock but wait will release lock
Service.isShutdown -> true if shutdown initiated. Will execute already running as well as
queued tasks
Serice.shutdownNow -> initiate shutdown and return all queued tasks. It will only execute
already running but NOT queued tasks
Service.awaitTermination -> block until all task are complete or if a timeout occurs
Service.isTerminated -> true if all tasks are complete
Thread starvation
Threads needs to wait for a very long wait time to acquire the lock and in case of unfair lock the wait
time can again increase. So eventually thread will starve off the CPU time.
Runnable vs callable
Callable can return and throw exception. Callable returns a future
Thread local
We know that all threads of an Object share it’s variables, so if the variable is not thread safe, we can
use synchronization but if we want to avoid synchronization, we can use ThreadLocal variables.
Every thread has its own ThreadLocal variable and they can use it gets () and set() methods to get
the default value or change it’s value local to Thread. ThreadLocal instances are typically private
static fields in classes that wish to associate the state with a thread.
Thread local makes sense when there is a thread pool (e.g. of 10 threads) which runs 1000 tasks
(runnable) then there will be only 10 simple date format objects instead of 1000 SDFs. It increases
memory efficiency and thread safety.
Synchronized block is not necessary as thread local are inherently thread safe. Hence it will increase
performance in multi-threaded environment.
https://stackoverflow.com/questions/817856/when-and-how-should-i-use-a-threadlocal-variable
https://stackoverflow.com/questions/1202444/how-is-javas-threadlocal-implemented-under-the-
hood
Future
https://www.baeldung.com/java-future
future.cancel – will cancel the task if not picked up if picked up then there will be no effect
(jvm will only attempt to stop but there is no guarantee)
future.isCancelled – task cancelled successfully
future.isDone – task completed
Completable future
Completable future is to enable async non-blocking api call done with the help of callback. If the
below was implemented with future.get() it will block all operations and make it synchronous. First
operation in the chain has to be asynchronous. By default, the same thread which did the first async
op will perform remaining op in the chain. If we want to other thread to do subsequent op then we
can use thenApplyAsync() instead of thenApply(). This is only helpful when we have a separate
thread pool to perform the subsequent async task. If no custom thread pool is supplied it takes the
default fork join pool.
https://www.baeldung.com/java-completablefuture
https://medium.com/javarevisited/java-completablefuture-c47ca8c885af#:~:text=With%20a
%20Future%20object%2C%20you,thenAccept()%20%2C%20or%20join()%20.
Try Lock
Try lock will try to acquire the lock and return true / false. Try lock without timeout does not honour
the fairness of a fair lock. To make try lock fair and not barge in, timeout of 0 should be specified
with trylock.
Try lock is good for not waiting and doing the alternate operation in case if the lock is not acquired.
Reentrant lock
Allows to call lock and unlock multiple times. Number of unlock calls has to match the number of
calls of lock. Useful for recursion scenarios. Can implement fair (first come first serve) - true / unfair
(barge in) - false lock in reentrant lock constructor.
In case of unfair lock, when thread1 release lock and thread 5 requested for lock then instead of
pushing to a thread lock queue to wait and acquire, thread 5 will directly get lock instead of thread 2
and 3 which were waiting in queue to get the lock
Reactive programming with Spring web Flux
Condition
Condtion is created on a lock (like re-entrant lock).It is used to coordinate between multiple threads.
Condtion.await – is a blocking to which will put the thread in wait state for the certain
condition to meet
Condition.signal – will make longest waiting threads back to runnable signalling the
condition has been met
Condition.signalAll – will make all the waiting threads back to runnable signalling the
condition has been met
Await will release the lock associated with the Condition. Current thread will not be able to
reacquire the lock until it has been signaled or interrupted. When a thread is signalled, it wakes up
and attempts to reacquire the lock on the object. If it is successful, it resumes execution from where
it left off before calling await().
Condition vs wait/notify
https://stackoverflow.com/questions/10395571/condition-vs-wait-notify-
mechanism#:~:text=Condition%20factors%20out%20the%20Object,use%20of%20arbitrary%20Lock
%20implementations.
Semaphore
It is to implement permit to a restricted resource which is in limited quantity. It has acquire and
release method. E.g. In a thread pool of 10 threads permit only 3 threads to perform certain actions.
How to pass input data to thread
Via constructor of the task (runnable implementation)
Or thread task can be completed using volatile or atomic boolean flag in runnable implementation
To schedule stopping using scheduledThreadPool
Synchronous Queue
It does not hold any element and has no size at all. It directly hands of item from producer to
consumer. Its different from blocking queue in put op i.e. when the queue is empty and producer
tries to put it will still be blocked until the consumer takes the item. Once consumer calls take, then
producer will put and consumer will take it. Its for direct hand off an item from one thread to
another thread
Deadlock
The order in which threads unlock mutexes does not matter. As long as a thread unlocks a mutex
that it has locked, there will be no deadlock. However, the order in which threads lock mutexes can
cause a deadlock.
A deadlock occurs when two or more threads are waiting for each other to unlock a mutex. This can
happen if one thread locks mutex A and then waits for mutex B to be unlocked, while another thread
locks mutex B and then waits for mutex A to be unlocked. In this case, neither thread will ever be
able to unlock the mutex that it is waiting for, and both threads will be deadlocked.
To avoid deadlocks, it is important to always lock mutexes in the same order across all threads that
access those mutexes. This means that if one thread locks mutex A and then mutex B, another
thread should not lock mutex B and then mutex A. Instead, the other thread should lock mutex A
and then mutex B.
Lock types – Object vs class
Synchronized on non-static method will acquire lock on this object i.e. on the object using which
method is called
https://stackoverflow.com/questions/3718148/java-class-level-lock-vs-object-level-lock
https://stackoverflow.com/questions/72349686/is-reentrant-lock-a-object-level-lock-or-class-level-
lock
https://stackoverflow.com/questions/23261120/difference-between-class-locking-and-object-
locking-in-java
https://stackoverflow.com/questions/26675381/what-are-class-level-object-level-explicit-and-
intrinsic-locking
https://stackoverflow.com/questions/22521377/class-level-and-object-level-lock-synchronization
Data Race
Any write of type int is atomic so data will not be corrupted but in case of double or long it can be
corrupted.
Race Condition
Race condition can happen with concurrentHashMap too. To avoid this the statements should be
executed atomically using lock or using compound operation of concurrentHashmap e.g.
putIfAbsent() or computeIfAbsent().
E.g. Count++ is 3 separate instruction (read, increment, write) and is not atomic.
Execute() vs submit() in executor service
https://stackoverflow.com/questions/2248131/handling-exceptions-from-java-executorservice-tasks
https://medium.com/@anuragsrivastava_35144/when-exception-occurs-in-a-running-thread-
537537b295b
https://dzone.com/articles/java-handling-runtimeexception
http://www.javabyexamples.com/handling-exceptions-from-executorservice-tasks
Executor service
https://www.baeldung.com/java-executor-service-tutorial
Thread pool
https://www.baeldung.com/thread-pool-java-and-guava
https://stackify.com/java-thread-pools/
Is executor thread better than stream parallel process? Which one to use when?
Latches
Atomic integer
AtomicInteger is a class in Java that provides atomic operations on an integer value. This means that
operations on the value are guaranteed to be thread-safe and will not be corrupted by concurrent
access from multiple threads.
AtomicInteger is typically used in multithreaded applications where multiple threads need to access
and update the same integer value. For example, AtomicInteger can be used to implement a counter
that is incremented by multiple threads.
Volatile keyword
Volatile is to make sure that any change done by a thread is visible to another thread. Exception
being compound operation like a++ (where there are 2 separate action fetch current value of a and
then incrementing it) where synchronized is also necessary
https://www.geeksforgeeks.org/print-even-and-odd-numbers-in-increasing-order-using-two-
threads-in-java/
https://www.javatpoint.com/java-program-to-print-even-odd-using-two-threads
https://www.linkedin.com/pulse/executing-2-threads-alternately-java-8-way-my-p-ashish-kumar-
singh/
Lock vs lockInterruptibly
https://stackoverflow.com/questions/17811544/actual-use-of-lockinterruptibly-for-a-reentrantlock
Memory Model