Multi-threading Flashcards

(161 cards)

1
Q

What is a Thread in Java?

A

A Thread is a lightweight process that runs within another process or thread. It is an independent path of execution in an application. JVM gives each thread its own method-call stack. When JVM starts it creates one thread that calls the main() method

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

What is a method-call stack in the context of a Thread?

A

Each thread in Java gets its own method-call stack from the JVM. This stack stores local variables - method parameters and the sequence of method calls for that thread only

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

How many threads does JVM start with by default?

A

JVM starts with one thread when it begins execution. This thread calls the main() method of the class passed as an argument to the java command

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

MEMORY BOOSTER: Thread in Java

A

Thread = lightweight process = independent execution path = own method-call stack. JVM starts with one thread (main). Each thread runs independently and can execute concurrently with other threads

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

What is the priority of a Thread and how is it used in scheduling?

A

Every thread has a priority from 1 to 10. The scheduler uses this priority to decide which thread gets CPU time first. Higher priority threads get preference over lower priority threads. This is called pre-emptive scheduling

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

What is the default priority of a thread in Java?

A

The default priority of a new thread is 5 which is NORM_PRIORITY. A new thread inherits the priority of its parent thread

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

What are the three priority constants available for a Thread in Java?

A

MIN_PRIORITY = 1 (lowest). NORM_PRIORITY = 5 (default). MAX_PRIORITY = 10 (highest)

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

How do you set the priority of a thread in Java?

A

Use setPriority(int priority) method. You can pass Thread.MIN_PRIORITY - Thread.NORM_PRIORITY or Thread.MAX_PRIORITY as the argument

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

MEMORY BOOSTER: Thread priority

A

Priority range: 1 to 10. MIN=1 - NORM=5 - MAX=10. Default is 5. Higher priority = more CPU preference. Set with setPriority(). Get with getPriority(). New thread inherits parent priority

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

What is the purpose of join() method in Thread class?

A

join() makes the current thread wait for the thread it is called on to finish before continuing execution. It ensures one thread completes before another starts

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

What happens when a thread calls join() on another thread?

A

The current thread stops executing and waits until the thread on which join() was called finishes running. Only then does the current thread resume

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

How can we ensure Parent thread waits for Child thread to finish?

A

Call join() on the child thread from the parent thread. The parent thread will block until the child thread finishes execution

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

MEMORY BOOSTER: join()

A

join() = wait for that thread to finish before I continue. importantThread.join() = current thread pauses until importantThread completes. Use it to enforce thread execution order

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

What is the fundamental difference between wait() and sleep() methods?

A

wait() is an Object level method that releases the monitor lock and can be woken up by notify(). sleep() is a static Thread method that does not release the monitor and cannot be woken up by notify()

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q

Does wait() release the monitor lock?

A

Yes - when a thread calls wait() it releases the monitor lock and enters waiting state. Another thread can then acquire the lock and call notify() to wake it up

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q

Does sleep() release the monitor lock?

A

No - sleep() does not release any locks or monitors. The thread simply pauses for the specified time while holding all its locks

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
17
Q

Where must wait() and notify() be called?

A

wait() and notify() must be called within the same synchronized block that is synchronized on the same monitor object

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
18
Q

MEMORY BOOSTER: wait() vs sleep()

A

wait() = Object method + releases lock + needs notify() to wake up + must be in synchronized block. sleep() = Thread static method + keeps lock + wakes up after time + no notify needed. wait = cooperative. sleep = timed pause

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
19
Q

Is it possible to call run() instead of start() on a thread in Java?

A

Yes but it will not run as a separate thread. It executes as a normal method call in the current thread with no context switching. Only start() creates a new thread

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
20
Q

MEMORY BOOSTER: run() vs start()

A

start() = creates new thread + calls run() in that new thread. run() directly = no new thread + executes in calling thread like a regular method. Always use start() to actually start a new thread

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
21
Q

How does Multi-threading work in Java?

A

Java allows one process to execute multiple threads in parallel. Each thread is created from a process and can run independently. Java provides methods like start() - notify() - wait() and sleep() to manage threads

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
22
Q

What are the advantages of Multi-threading?

A

Improved performance - simultaneous access to multiple applications - reduced number of servers needed - and simplified coding for certain parallel tasks

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
23
Q

What are the disadvantages of Multi-threading?

A

Difficult to debug - difficult to manage concurrency - difficult to convert single-threaded code to multi-threaded - and risk of deadlocks

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
24
Q

MEMORY BOOSTER: Multi-threading pros and cons

A

Pros: performance + parallelism + fewer servers + simpler parallel code. Cons: hard to debug + concurrency issues + porting difficulty + deadlock risk. Multi-threading is powerful but complex - use only when needed

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
25
What are the differences between Pre-emptive Scheduling and Time Slicing Scheduler?
Pre-emptive scheduling runs the highest priority thread until it waits or dies or a higher priority thread arrives. Time slicing gives each thread a fixed time slot then moves to the next thread based on priority and other factors
26
MEMORY BOOSTER: Pre-emptive vs Time Slicing
Pre-emptive = highest priority runs until it stops or is replaced. Time slicing = everyone gets a time slot in rotation. Pre-emptive is priority-driven. Time slicing is fairness-driven
27
What is a daemon thread in Java?
A daemon thread is a low priority background thread that does not prevent JVM from exiting when the program finishes. Garbage Collection is a classic example of a daemon thread
28
How can we make a regular thread a daemon thread in Java?
Call setDaemon(true) on the thread before it is started. Once a thread has started you cannot change its daemon status
29
What happens if you call setDaemon() on an already started thread?
It throws IllegalThreadStateException. Daemon status can only be set before the thread starts
30
MEMORY BOOSTER: Daemon thread
Daemon thread = background + low priority + does not block JVM shutdown. Set with setDaemon(true) BEFORE start(). GC is a daemon thread. After thread.start() it is too late - calling setDaemon() throws IllegalThreadStateException
31
Can we start a thread two times in Java?
No - start() can only be called once on a Thread. Calling it a second time throws IllegalThreadStateException
32
MEMORY BOOSTER: Starting thread twice
One thread - one start(). Calling start() twice throws IllegalThreadStateException. If you need to run the same task again create a new Thread instance
33
In what scenarios can we interrupt a thread?
We can interrupt a thread to wake it up from sleep or wait state. Interruption signals the thread to stop what it is doing and handle the interruption
34
Can we wake up a thread put to sleep by Thread.sleep()?
Yes - call interrupt() on the thread. The sleeping thread will receive InterruptedException which wakes it up from sleep
35
What are the two ways to check if a thread has been interrupted?
1) Call Thread.interrupted() static method which also clears the interrupted flag. 2) Call isInterrupted() instance method which checks the flag without clearing it
36
MEMORY BOOSTER: Interrupting a thread
interrupt() = send interruption signal. Sleeping/waiting thread wakes up with InterruptedException. Check interruption with: Thread.interrupted() (clears flag) or isInterrupted() (keeps flag). Always handle InterruptedException properly
37
In Java is it possible to lock an object for exclusive use by a thread?
Yes - use a synchronized block to lock an object. Only the thread holding the lock can access the locked object. All other threads are blocked until the lock is released
38
MEMORY BOOSTER: Locking an object
synchronized(myObject) { ... } = exclusive lock on myObject. Only one thread inside at a time. Other threads wait. Lock is released when the block exits normally or via exception
39
How is notify() different from notifyAll() method?
notify() wakes up one specific waiting thread (chosen arbitrarily by JVM). notifyAll() wakes up all threads that are waiting on the object monitor
40
When should you use notifyAll() instead of notify()?
Use notifyAll() when multiple threads may be waiting and all of them need to re-evaluate the condition. notify() risks waking the wrong thread leaving others stuck waiting
41
MEMORY BOOSTER: notify() vs notifyAll()
notify() = wake ONE waiting thread (JVM chooses). notifyAll() = wake ALL waiting threads. When in doubt use notifyAll() to avoid leaving threads stuck. notify() is an optimization for specific known scenarios
42
What is a Shutdown hook in Java?
A shutdown hook is a thread that JVM invokes automatically just before shutting down. It is used to clean up resources. Register it with Runtime.addShutdownHook(Thread hook)
43
MEMORY BOOSTER: Shutdown hook
Shutdown hook = thread auto-run by JVM at shutdown. Register with Runtime.getRuntime().addShutdownHook(myThread). Good for cleanup - closing connections or saving state before JVM exits
44
What is synchronization in Java?
Synchronization is a feature in Java multi-threading that controls access of multiple threads to a shared resource. It prevents thread interference and memory inconsistency issues and helps avoid deadlocks
45
What is the purpose of a synchronized block in Java?
A synchronized block prevents thread interference - avoids memory inconsistency issues and has a smaller scope than a synchronized method making it more efficient for fine-grained locking
46
What is static synchronization in Java?
When a static method is marked as synchronized the lock is on the Class object not on an instance. This means only one thread can execute any static synchronized method of that class at a time
47
MEMORY BOOSTER: Synchronization
synchronized method = locks the object instance. synchronized block = locks any specified object (more flexible). static synchronized = locks the Class. Synchronization prevents race conditions but adds overhead
48
What is a Deadlock situation?
Deadlock occurs when two or more threads are each waiting for a resource held by the other creating a circular wait where no thread can proceed
49
What are the minimum requirements for a Deadlock to occur?
Mutual exclusion (resource used by one thread at a time) + Resource holding (thread holds one lock while waiting for another) + No preemption (lock cannot be forcibly taken) + Circular wait (threads wait in a circular chain)
50
How can we prevent a Deadlock?
Remove at least one of the four conditions: use optimistic locking to avoid mutual exclusion - release all locks if not all can be acquired - use timeouts on locks - ensure all threads acquire locks in the same fixed order to prevent circular wait
51
How can we detect a Deadlock in Java?
Use ThreadMXBean.findDeadlockedThreads() method from java.lang.management package. It returns the thread IDs of all deadlocked threads or null if none exist
52
MEMORY BOOSTER: Deadlock
4 conditions needed: Mutual exclusion + Resource holding + No preemption + Circular wait. Remove ANY ONE condition to prevent deadlock. Detect with ThreadMXBean.findDeadlockedThreads(). Fix: consistent lock ordering - timeouts - try-lock
53
What is the meaning of concurrency?
Concurrency is the ability of a program to execute multiple tasks simultaneously by distributing computations over multiple CPU cores or machines. It increases execution speed in multi-processor or multi-core systems
54
MEMORY BOOSTER: Concurrency
Concurrency = multiple tasks making progress at the same time. Achieved by multi-threading or multi-processing. Not the same as parallelism - concurrent tasks may take turns rather than literally running at the same instant
55
What is the main difference between a process and a thread?
A process runs in its own private memory space. A thread runs within a process and shares memory and resources with other threads of the same process. Threads are lighter and more efficient for performance-critical tasks
56
What is a process and thread in the context of Java?
In Java a process refers to the running JVM instance. A thread lives within the JVM and can be created or stopped by the Java application at runtime
57
MEMORY BOOSTER: Process vs Thread
Process = own memory space + heavier + isolated. Thread = shared memory within process + lighter + faster communication. In Java: process = JVM. Thread = unit of execution inside JVM. Threads share heap but have their own stack
58
What is a Scheduler?
A Scheduler is a program implementing a scheduling algorithm that manages CPU or I/O access for processes and threads. Its goal is load balancing and ensuring each thread gets reasonable CPU time
59
What is the minimum number of threads in a Java program?
Every Java application has at least one thread - the main thread that starts when java.exe launches and calls the main() method
60
MEMORY BOOSTER: Scheduler
Scheduler = traffic controller for threads. Decides which thread runs next based on priority - time slice or other algorithms. Java has at least 1 thread (main). More threads = more scheduling complexity
61
What are the properties of a Java thread?
Each thread has: an ID (long - unique in JVM) - a Name (String) - a Priority (int) - a State (java.lang.Thread.State) - and a Group (ThreadGroup it belongs to)
62
MEMORY BOOSTER: Thread properties
5 properties: ID (unique long) + Name (String) + Priority (int 1-10) + State (New/Runnable/Blocked/Waiting/TimedWaiting/Terminated) + Group (ThreadGroup). Get them with getId() - getName() - getPriority() - getState() - getThreadGroup()
63
What are the different states of a Thread in Java?
New (not yet started) - Runnable (executing in JVM) - Blocked (waiting for monitor lock) - Waiting (waiting indefinitely for notify) - Timed_Waiting (waiting for a specified time) - Terminated (finished execution)
64
What is the difference between Blocked and Waiting state of a thread?
Blocked means the thread is waiting to acquire a monitor lock to enter a synchronized block. Waiting means the thread is waiting indefinitely for another thread to call notify() or notifyAll()
65
What is Timed_Waiting state in a thread?
A thread is in Timed_Waiting state when it is waiting for another thread to perform an action within a specified time limit - for example when sleep() or join(timeout) is called
66
MEMORY BOOSTER: Thread states
6 states: New > Runnable > Blocked/Waiting/Timed_Waiting > Terminated. Blocked = waiting for lock. Waiting = waiting for notify(). Timed_Waiting = waiting with timeout. Think of it as the lifecycle of a thread from birth to death
67
What is the purpose of Thread Groups in Java?
Every thread belongs to a ThreadGroup. ThreadGroup provides methods to perform collective actions on all threads in the group such as interrupting all threads or setting maximum priority for the whole group
68
MEMORY BOOSTER: Thread Groups
ThreadGroup = container for threads. Allows bulk operations: interrupt all - set max priority for all. Every thread belongs to a group. Useful for managing related threads as a single unit
69
Why should we not stop a thread by calling its stop() method?
stop() is deprecated. When called it unlocks all monitors the thread holds. This leaves shared objects in an inconsistent state that other threads may see - causing unpredictable behavior
70
How should we stop a thread safely in Java?
Use a volatile boolean flag or a volatile Thread reference. Set the flag to false or the reference to null to signal the thread to stop. The thread checks this flag in its run() loop and exits gracefully
71
MEMORY BOOSTER: Do not use stop()
stop() = deprecated + dangerous. It releases all locks immediately leaving objects in broken state. Instead use a volatile flag variable to signal the thread to stop gracefully. Let the thread exit its own run() loop
72
What are the two main ways to create a Thread in Java?
1) Extend Thread class and override run() method then call start(). 2) Implement Runnable interface - pass the Runnable to a Thread constructor and call start()
73
Which is preferred - extending Thread or implementing Runnable?
Implementing Runnable is preferred because Java does not support multiple inheritance. Implementing Runnable allows the class to extend another class while still being used as a thread task
74
MEMORY BOOSTER: Creating a Thread
Two ways: extend Thread (override run()) OR implement Runnable (pass to new Thread()). Always call start() not run() to create a new thread. Runnable is preferred because it separates task from thread and supports inheritance
75
How do you access the current thread in a Java program?
Call the static method Thread.currentThread() which returns a reference to the currently executing Thread object. You can then call getId() or getName() on it
76
MEMORY BOOSTER: Current thread access
Thread.currentThread() = reference to the thread currently executing this code. Use it to get ID - name - priority or state of the running thread. It is a static method so no instance needed
77
What is Busy waiting in Multi-threading?
Busy waiting (also called busy-looping or spinning) is when a thread repeatedly checks a condition in a loop without sleeping. It wastes CPU time and is considered an anti-pattern
78
How can we prevent busy waiting in Java?
Use Thread.sleep(milliseconds) to pause the thread between checks. This frees the CPU for other threads instead of spinning in a loop
79
MEMORY BOOSTER: Busy waiting
Busy waiting = while(condition) {} loop without sleep = CPU waste = anti-pattern. Fix: add Thread.sleep() inside the loop or better yet use wait()/notify() to block and wake the thread only when needed
80
Can we use Thread.sleep() for real-time processing in Java?
No - Java does not guarantee that sleep() will pause for exactly N milliseconds. The thread may sleep longer than requested. For real-time processing precise timing is required so sleep() is not recommended
81
MEMORY BOOSTER: sleep() and real-time
Thread.sleep(N) = pause for AT LEAST N ms but maybe more. JVM gives no precision guarantee. Do NOT use for real-time processing where exact timing matters. Use real-time operating system or specialized libraries instead
82
How will you handle InterruptedException in Java?
Do not ignore it or just log it. The run() method cannot throw checked exceptions so you must handle it inside run(). The correct approach is to check the interruption and take appropriate action like stopping the thread gracefully
83
MEMORY BOOSTER: Handling InterruptedException
Never swallow InterruptedException silently. Do not just catch and log. Handle it meaningfully - usually stop the thread or restore the interrupted status with Thread.currentThread().interrupt(). Ignoring it hides important thread coordination signals
84
Which intrinsic lock is acquired by a synchronized method in Java?
A synchronized method acquires the intrinsic lock of the object instance (this) it belongs to. For static synchronized methods it acquires the lock of the Class object
85
Can we mark a constructor as synchronized in Java?
No - constructors cannot be synchronized. The compiler will give an error. Only the constructing thread can access the object being built so synchronization is unnecessary
86
Can we use primitive values for intrinsic locks?
No - intrinsic locks require Object references. Primitives like int or boolean cannot be used as lock monitors
87
Do intrinsic locks have re-entrant property in Java?
Yes - intrinsic locks are re-entrant. The same thread can acquire the same lock multiple times without deadlocking itself. The lock is released only when the thread exits all synchronized blocks for that lock
88
MEMORY BOOSTER: Intrinsic locks
synchronized method = locks 'this'. static synchronized = locks Class object. No primitives as locks. Re-entrant = same thread can re-acquire its own lock. Lock released on normal exit OR exception
89
What is an atomic operation?
An atomic operation completes in a single indivisible step relative to other threads. It either fully executes or does not execute at all - there is no in-between state visible to other threads
90
Is i++ an atomic operation in Java?
No - i++ involves three steps: read current value + increment + write back. A thread can be interrupted between any of these steps making it non-atomic
91
What are the atomic operations in Java?
Read and write operations on reference variables and most primitives (except long and double) are atomic. Read and write on volatile variables (including long and double) are also atomic
92
Which Java classes use CAS operations internally?
Classes like AtomicInteger - AtomicBoolean - AtomicLong in the java.util.concurrent.atomic package use Compare-And-Swap operations internally
93
What is a CAS (Compare-And-Swap) operation?
CAS is a CPU-level instruction that updates a value only if it currently matches an expected value. If another thread changed the value first the update fails and the thread retries. It is the basis of optimistic locking
94
MEMORY BOOSTER: Atomic operations
Atomic = all or nothing - no partial state visible. i++ is NOT atomic (3 steps). Use AtomicInteger for thread-safe counters. CAS = compare current value + swap if matches = optimistic locking without synchronized. Package: java.util.concurrent.atomic
95
Why is the double-checked locking Singleton not thread-safe without volatile?
The JIT compiler can reorder bytecode so the reference to the instance is set before the constructor finishes. Another thread may see a non-null but partially initialized object. Adding volatile to the instance field prevents this reordering
96
MEMORY BOOSTER: Thread-safe Singleton
Double-checked locking needs volatile on the instance field. Without volatile: JIT reorders bytecode = partially constructed object returned. With volatile: write completes before reference is published. Pattern: private volatile static Instance instance
97
What is a Livelock?
Livelock is when two or more threads keep changing their state in response to each other without making any progress. Unlike deadlock where threads are stuck waiting - in livelock threads are active but accomplishing nothing
98
What is the difference between Deadlock and Livelock?
In Deadlock threads are blocked and waiting - doing nothing. In Livelock threads are actively running and responding to each other but neither makes actual progress. Livelock is harder to detect because threads appear busy
99
MEMORY BOOSTER: Livelock
Deadlock = threads frozen waiting. Livelock = threads busy but going nowhere. Like two people in a hallway who keep stepping the same direction to let each other pass. Both are moving but neither gets through
100
What is Thread starvation?
Thread starvation occurs when a lower priority thread cannot get enough CPU time because higher priority threads keep getting scheduled. The low priority thread never or rarely gets to run
101
How can a synchronized block cause Thread starvation?
If many threads wait to enter a synchronized block there is no guarantee about the order they enter. Some threads may be repeatedly passed over and starve waiting for their turn
102
MEMORY BOOSTER: Thread starvation
Starvation = low priority thread never gets enough CPU time. Cause: high priority threads dominate + unfair synchronized block access. Fix: use fair locks (ReentrantLock with fairness=true) to guarantee oldest waiting thread gets access first
103
What is a Race condition?
A race condition is when a program tries to perform two or more operations simultaneously that must be done in a specific order to work correctly. It is a bug where the outcome depends on the timing of thread execution
104
Give an example of a race condition.
if(x == 3) then y = x * 5 - if another thread changes x between the check and the act then y will not equal 15. This check-then-act pattern is a classic race condition
105
MEMORY BOOSTER: Race condition
Race condition = outcome depends on thread timing = non-deterministic bug. Classic pattern: check-then-act. Thread A checks - Thread B changes value - Thread A acts on stale value. Fix: synchronize the check-and-act as a single atomic block
106
What is a Fair lock in multi-threading?
A fair lock (ReentrantLock with fairness=true) gives access to the longest-waiting thread first. It prevents thread starvation but reduces overall throughput since slow threads get locks repeatedly
107
What class implements Fair lock in Java?
ReentrantLock class with the fairness parameter set to true implements a fair lock: new ReentrantLock(true)
108
What is the downside of a Fair lock?
Lower throughput - since even slow or low-priority threads get locks regularly - the overall speed of the program decreases. Also tryLock() does not honor the fairness parameter
109
MEMORY BOOSTER: Fair lock
ReentrantLock(true) = fair lock = longest waiting thread goes first = no starvation. Trade-off: lower throughput. ReentrantLock(false) = unfair lock = faster but may starve threads. tryLock() ignores fairness regardless
110
Which two Object class methods are used to implement Producer Consumer scenario?
wait() and notify(). The Consumer calls wait() to pause until the Producer produces something. The Producer calls notify() to wake the Consumer after producing
111
How does JVM decide which thread to wake on notify()?
JVM wakes one arbitrary thread - the choice is implementation-dependent and not guaranteed. There is no rule specifying which waiting thread gets woken. Use notifyAll() to wake all waiting threads when order matters
112
MEMORY BOOSTER: Producer Consumer
Producer calls notify() after producing. Consumer calls wait() when nothing to consume. Both must be in synchronized block on same monitor. JVM picks an arbitrary thread on notify(). Use notifyAll() if multiple consumers wait
113
How can we check if a thread has a monitor lock on a given object?
Use Thread.holdsLock(Object obj) static method. It returns true if the current thread holds the lock on the specified object
114
MEMORY BOOSTER: holdsLock()
Thread.holdsLock(obj) = does current thread own the lock on obj? Returns boolean. Useful for assertions in debugging: assert Thread.holdsLock(myObject) to verify locking assumptions
115
What is the use of yield() method in Thread class?
yield() hints to the scheduler that the current thread is willing to give up its CPU time. The scheduler may ignore this hint. It is mainly used for testing or debugging and rarely has a concrete practical use
116
MEMORY BOOSTER: yield()
yield() = polite suggestion to scheduler to give CPU to another thread. Scheduler can ignore it. Not guaranteed to do anything. Not used in production code. More useful in testing multi-threading scenarios
117
What is the most important point when passing an object between threads?
Ensure that two threads cannot update the same object at the same time. The safest approach is to make the object immutable so no thread can modify it after creation
118
What are the rules for creating Immutable Objects in Java?
No setter methods + all fields final and private + class declared final (or constructor private with factory methods) + no methods that modify mutable fields + copy mutable objects passed to constructor and never return originals
119
MEMORY BOOSTER: Immutable objects for thread safety
Immutable = thread-safe by design. Rules: no setters + all fields final+private + final class + copy mutable inputs + never expose mutable internals. String and Integer are classic immutable classes. Immutability eliminates the need for synchronization
120
What is the use of ThreadLocal class?
ThreadLocal provides thread-local variables where each thread has its own independent copy of the variable. Changes in one thread do not affect other threads. Typically used as private static fields
121
What are the scenarios suitable for using ThreadLocal?
Transporting security or login information within a request. Storing transaction context across method calls without passing it as a parameter. Any scenario where each thread needs its own isolated copy of shared data
122
MEMORY BOOSTER: ThreadLocal
ThreadLocal = one variable + separate copy per thread. Thread X gets its own value. Thread Y gets its own value. They never see each other. Use for: per-request security context - database connections - transaction IDs. Private static field is the typical pattern
123
How can multi-threading improve the performance of an application?
By parallelizing tasks across multiple CPU cores. For example processing 1000 files sequentially takes 5000 minutes. With 10 parallel threads each handling 100 files it takes only 500 minutes
124
What is scalability in a software program?
Scalability is the ability of a program to handle growing amounts of work - data or users without failing. A scalable program can accommodate growth by adding more resources
125
What is Amdahl's law?
Amdahl's law gives the formula for maximum theoretical speedup: S(n) = 1 / (B + (1-B)/n) where n = number of processors and B = fraction that must run serially. It shows that the serial portion limits maximum speedup regardless of how many processors you add
126
MEMORY BOOSTER: Amdahl's law
S(n) = 1 / (B + (1-B)/n). B = serial fraction. n = processors. As n approaches infinity speedup approaches 1/B. Lesson: even a small serial portion severely limits parallel speedup. Minimize serial code to maximize multi-threading benefit
127
What is Lock contention in multi-threading?
Lock contention occurs when one thread is waiting for a lock held by another thread. The waiting thread cannot proceed until the lock is released. Also called Thread contention
128
What are the techniques to reduce Lock contention?
Reduce scope of lock + reduce object pooling + reduce lock acquisition frequency + avoid unnecessary synchronization + use hardware-supported optimistic locking (CAS) instead of synchronization
129
What is Lock splitting technique?
Lock splitting divides one coarse-grained lock into multiple finer locks protecting different parts of the same application. For example giving each array element its own lock instead of one lock for the whole array
130
What is Lock striping?
Lock striping uses multiple locks to protect different parts of the same data structure. ConcurrentHashMap uses lock striping by assigning different locks to different buckets allowing concurrent access to different parts of the map
131
What technique does ReadWriteLock use to reduce Lock contention?
ReadWriteLock uses two separate locks: a read lock that multiple threads can hold simultaneously and a write lock that is exclusive. This allows many concurrent readers while ensuring exclusive write access
132
MEMORY BOOSTER: Lock contention techniques
Reduce scope + fewer lock acquisitions + avoid unnecessary sync + use CAS. Advanced: Lock splitting (one lock per element) + Lock striping (one lock per bucket like ConcurrentHashMap) + ReadWriteLock (many readers + one writer)
133
Is it always beneficial to use object pooling in a multi-threading application?
No - in multi-threading an object pool requires synchronized access adding lock contention overhead. This overhead can outweigh the performance gain from object reuse making pooling counterproductive
134
MEMORY BOOSTER: Object pooling in multi-threading
Single-thread: object pooling = good performance. Multi-thread: object pool = synchronized access = lock contention = may be slower. Always benchmark before assuming pooling helps in concurrent scenarios
135
What is the relation between Executor and ExecutorService interface?
Executor has only execute(Runnable) method. ExecutorService extends Executor and adds shutdown() - invokeAll() - invokeAny() and awaitTermination() methods for lifecycle management and batch task execution
136
What happens when you call submit() on an ExecutorService whose queue is full?
It throws RejectedExecutionException because the service cannot accept new tasks when its queue is already at capacity
137
What is a ScheduledExecutorService?
ScheduledExecutorService extends ExecutorService and adds schedule() methods to run tasks after a delay or at fixed intervals using scheduleAtFixedRate() and scheduleWithFixedDelay()
138
How will you create a Thread pool in Java?
Use Executors.newFixedThreadPool(int nThreads) to create a fixed-size thread pool. Submit tasks using submit() or execute() and call shutdown() when done
139
MEMORY BOOSTER: Executor framework
Executor = just execute(Runnable). ExecutorService = Executor + lifecycle (shutdown + await) + batch (invokeAll/Any). ScheduledExecutorService = ExecutorService + time-based scheduling. Thread pool: Executors.newFixedThreadPool(n)
140
What is the main difference between Runnable and Callable interface?
Runnable.run() returns void and cannot throw checked exceptions. Callable.call() returns a value and can throw checked exceptions. Callable was added in Java 1.5
141
What is the Future interface used for in Java?
Future represents the result of an asynchronous computation. It provides isDone() to check completion - isCancelled() to check cancellation - cancel() to attempt cancellation and get() to retrieve the result
142
MEMORY BOOSTER: Runnable vs Callable vs Future
Runnable = run() + no return + no checked exception. Callable = call() + returns value + can throw. Future = handle to async result + isDone() + get() + cancel(). Submit Callable to ExecutorService and get back a Future
143
What is a Semaphore in Java?
Semaphore is a class that controls how many threads can access a resource or critical section concurrently. It maintains a set of permits. acquire() gets a permit (blocks if none available). release() returns a permit
144
MEMORY BOOSTER: Semaphore
Semaphore = counting gate. new Semaphore(3) = max 3 threads at a time. acquire() = request entry (wait if full). release() = exit (free a slot). Use to limit concurrent access to a resource like a database connection pool
145
What is a CountDownLatch in Java?
CountDownLatch allows one or more threads to wait until other threads complete. A counter is decremented by countDown() calls. When it reaches zero all threads waiting at await() are released
146
What is the difference between CountDownLatch and CyclicBarrier?
CountDownLatch is one-time use - counter cannot be reset. CyclicBarrier resets after all threads arrive and can be reused. CyclicBarrier can also run a Runnable task when the barrier is reached. CyclicBarrier is better for repeated rendezvous points
147
MEMORY BOOSTER: CountDownLatch vs CyclicBarrier
CountDownLatch = one-shot countdown + threads wait at await() + counter set once. CyclicBarrier = reusable + all threads meet at barrier + optional Runnable on completion. Latch for start signal. Barrier for repeated synchronization points like MapReduce rounds
148
What are the scenarios suitable for using Fork/Join framework?
Fork/Join is ideal for divide-and-conquer algorithms where a large task is split into smaller subtasks recursively. fork() starts async execution. join() waits for result. ForkJoinPool manages the threads
149
What is the difference between RecursiveTask and RecursiveAction?
RecursiveTask.compute() returns a value - use when the task computes and returns a result. RecursiveAction.compute() returns void - use when the task directly operates on a data structure without returning a value
150
MEMORY BOOSTER: Fork/Join
Fork = split task + start async. Join = wait for result. RecursiveTask = compute() returns value. RecursiveAction = compute() returns void. ForkJoinPool uses work-stealing to keep all threads busy. Best for divide-and-conquer
151
Can we process stream operations with a Thread pool in Java 8?
Yes - use parallelStream() on a Collection or call parallel() on an existing stream to process it using the common ForkJoinPool
152
When should you use parallel streams in Java 8?
Use parallel streams when: there are many items to process + each item takes significant time + processing is parallelizable + there is no existing multi-threading environment. Parallel streams have high overhead so avoid them for small datasets
153
MEMORY BOOSTER: Parallel streams
parallelStream() or stream().parallel() = uses ForkJoinPool. HIGH overhead - only use for large datasets with expensive per-item processing. Do NOT use in already multi-threaded code - can degrade performance. Always benchmark before switching to parallel
154
How do Stack and Heap work in a Java multi-threading environment?
Each thread has its own Stack (local variables - method params - call stack). All threads share the Heap (all objects). Local variables in one thread are invisible to other threads. Shared Heap objects can cause race conditions - use volatile to ensure threads read the latest value from main memory
155
What is the volatile keyword used for in multi-threading?
volatile ensures that reads and writes of a variable always go to and from main memory and are visible to all threads immediately. It prevents thread-local caching of variables
156
MEMORY BOOSTER: Stack vs Heap in multi-threading
Stack = private per thread = local vars + method params + NOT shared. Heap = shared by all threads = all objects = risk of race conditions. volatile = force reads/writes to main memory = all threads see latest value. Private stack = safe. Shared heap = needs synchronization
157
How can we take a Thread dump in Java?
Windows: Ctrl+Break. Linux: kill -3 . Or use jstack tool: jstack . Thread dump shows the state of all threads in the JVM at that moment
158
Which parameter controls the stack size of a thread in Java?
-Xss parameter controls thread stack size. For example -Xss1m sets each thread stack to 1MB
159
MEMORY BOOSTER: Thread dump and stack size
Thread dump: Windows=Ctrl+Break - Linux=kill -3 - always=jstack . Stack size: -Xss parameter e.g. -Xss512k. Thread dump is your best debugging tool for deadlocks and hung threads - it shows every thread state and stack trace
160
How will you ensure threads T1 and T2 run in sequence T1 then T2?
Start T1 first. Then call T1.join() before starting T2. T2 will not start until T1 has finished. Alternatively start T2 first but inside T2's run() call T1.join() so T2 waits for T1 before doing its work
161
MEMORY BOOSTER: Enforce thread execution order
Use join() to sequence threads. To run T1 then T2: t1.start() then t1.join() then t2.start(). join() = wait for that thread to finish. Chain join() calls to enforce any ordering between threads