Detailed FAQ on Java thread concurrency basics for interviews and hands-on programming concepts.

6.How to start a thread in Java and why you should not call the run() method explicitly?
To start a thread in Java, one should invoke the start() method from an instance of the Thread class. This method actually starts the mechanism of creating the new thread in the queue of the scheduler to run it on its own side from the original thread.
A simple example can be seen in the following listing:
Thread thread = new MyThread();
thread.start();
The start() method is important to use because it starts the thread in its own execution path. If you call run() directly, it will behave like any other method in the same thread. In other words, code inside run() will not execute in a different thread but rather block the current thread until that finishes. Always use start() for true multithreading.


7.What are the Different States of a Thread's Life Cycle?
In Java, a thread passes through different states as its lifetime evolves, which are called its life cycle collectively.
Now, let's see the states in detail:
New: After a thread object has been created but is not yet started, the thread is in New.
Example:
Thread t = new Thread();
Runnable: After call to start(), the thread turns into a Runnable. In this state, it is ready to run but it needs to wait until the CPU gives it the priority to run on.
Blocked: A thread turns into the Blocked state if a thread tries to access an unavailable resource, like the locked object. The thread stays in this state till the resource becomes available.
Waiting: A thread is in the Waiting state if it pauses for an indefinite period, waiting for another thread to notify or signal it.
Timed Waiting: A thread goes into the Timed Waiting state when it waits for a definite period and this is caused by methods such as Thread.sleep() or join() with a timeout value.
Terminated: Once a thread has completed its task or has been stopped, it moves to the Terminated state. At this point, it cannot be restarted.
Understanding these states helps in writing better code that can handle concurrency efficiently.


8.What Is Thread.sleep() and How Does It Impact a Thread's Execution?
The Thread.sleep(long millis) method causes the current thread to sleep for a specified number of milliseconds. This makes the thread enter the Timed Waiting state and stops consuming CPU cycles. Thus, sleep() can be used as a tool to add delays without putting extra load on the processor.
Once the sleep duration has elapsed, the thread reverts back to Runnable and waits for the CPU to schedule it to run.
Usage:
try {
Thread.sleep(2000); /* Sleep for 2 seconds */
} catch (InterruptedException e) {
e.printStackTrace();
}
Note, though; while sleep() can sometimes assist in making the timing for running a thread easier to implement, overdoing it can have efficiency penalties. Use it with discretion and only when there is a genuine need for intentional delay.


9.What is thread priority in Java and how do you set it?
In Java, the thread priority indicates the relative importance of a thread for ordering execution. The thread with a higher priority will most probably receive more CPU time compared to a thread having lower priority. However, it's left to the discretion of the operating system's thread scheduler as to the final scheduling of the threads. Therefore, the thread's priority doesn't necessarily determine its execution order.
To set the priority of a thread the setPriority(int priority) method is used. The valid range of priorities is from Thread.MIN_PRIORITY (1) to Thread.MAX_PRIORITY (10) and the default value is Thread.NORM_PRIORITY (5).
Here’s an example of how to set a thread's priority:
Thread thread = new Thread();
thread.setPriority(Thread.MAX_PRIORITY); /* Assign the highest priority to the thread */
Thread priority can affect the order of thread execution. however, their use for management of threads should not be left solely to priority as different behavior may result on different platforms.


10.How Does Thread.join() Function in Java?
The join() method is a mechanism that allows one thread to wait until another thread has completed its execution. If a thread calls join() on another thread the calling thread pauses and resumes only after the specified thread has finished. This feature is especially useful when certain tasks need to be executed sequentially.
Example:
Thread t1 = new Thread(() -> System.out.println("Task in thread 1"));
Thread t2 = new Thread(() -> System.out.println("Task in thread 2"));
t1.start();
t2.start();
try {
t1.join(); /* Waits for t1 to finish before proceeding */
t2.join(); /* Waits for t2 to finish*/
}
catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Both threads have completed their tasks.");
In this example, the main thread waits for t1 and t2 to complete before printing the final message. It ensures that the program executes according to a set order.


11.What is the Difference Between a Daemon Thread and a User Thread in Java?
Java divides its threads into daemon threads and user threads. Each type has been designed to perform a different function in an application.
Daemon Threads:
These are background threads for auxiliary tasks such as garbage collection or resource monitoring. If the application ends the JVM is not going to wait till the daemon threads get completed. Once all user threads terminate, the JVM will shut down whether the daemon threads are running or not.
To make a daemon thread before its start you have to call the setDaemon(true) method.
Here is an example:
Thread daemonThread = new Thread(() -> System.out.println("This is a daemon thread."));
daemonThread.setDaemon(true); /* Mark the thread as a daemon */
daemonThread.start();
User Threads:User threads do the main jobs of an application and need to finish before the JVM shuts down. These threads keep the application alive and the JVM will not exit until all user threads have finished their execution.


12.What is a Thread Pool in Java and How Does it Help to Manage Threads?
A thread pool in Java is a pool of pre-created reusable threads that execute tasks. Rather than creating a new thread for each task an operation that can be resource intensive the thread pool uses existing threads to perform several tasks. This approach enhances performance, saves system resources and reduces the time spent on thread creation and termination.
Java provides an interface called ExecutorService to manage thread pools. This interface provides the ability to submit tasks into the pool and have threads that execute them. Once a task is completed the thread goes back to the pool to await further tasks.
The main benefits of using a thread pool include efficient resource management, more control over concurrency and reduced overhead due to constant creation of new threads.

Here is an example of using a thread pool:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPoolExample {
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(5); /* Creating a thread pool with 5 threads*/
for (int i = 1; i <= 10; i++) {
int taskNumber = i
; executor.submit(() -> System.out.println("Executing Task " + taskNumber)); // Submitting tasks
}
executor.shutdown(); // Shutting down the executor after task completion
}
}
In this example, the pool of threads ensures efficient task execution while controlling resource usage.


13.What is Thread Synchronization and Why is it Important in Java? Thread synchronization is actually a mechanism or a way by which only one thread can possibly access a shared resource at one time. When many threads are trying to change the same data simultaneously, synchronization is crucial since concurrent modifications may lead to unpredictable or inconsistent results or even corrupt shared resources if not properly synchronized.
Synchronization can be done using the synchronized keyword in Java. It can be applied to an entire method or to a particular block of code. It helps ensure that in a multithreaded program, no thread accesses a critical section of code at any one time. In this way, data consistency is ensured and race conditions are avoided.
Example:
public class Counter {
private int count = 0;
/* The increment method is synchronized to ensure thread safety */
public synchronized void increment() {
count++;
}
public int getCount() {
return count;
}
}
In the above example, the increment() method is synchronized. It ensures that only one thread may modify the count variable at any given time. This is more critical in multi-threaded applications wherein data integrity should be preserved during concurrent access.


14.Difference Between wait(), notify(), and notifyAll() in Java?
The methods wait(), notify() and notifyAll() in Java are used for inter thread communication, so that threads may coordinate their execution in a multi-threaded environment. They help in managing the synchronization of threads while they wait or otherwise notify each other about certain conditions.
wait():
It calls the wait() method, pausing the execution of the current thread until another thread that waits on it comes to know to bring it out of this wait mode.
A thread invokes wait() within a synchronized block, thus it releases the lock it holds on the object's monitor and goes into waiting state.
Example:
synchronized (lock) {
lock.wait(); /* The current thread pauses here */
}
notify():
This method notify() wakes up one of the threads waiting on an object's monitor. In case more than one thread is waiting, just one of them is selected to continue its execution. The choice of which thread is notified depends on the thread scheduler.
/* Notify a single waiting thread */
synchronized (lock) {
lock.notify();
}
notifyAll():
The notifyAll() method wakes all threads waiting on the object's monitor. The awakened threads will then contend for the lock and one of the threads will be resumed to its execution.
synchronized (lock) {
lock.notifyAll(); // Notifies all threads waiting
}
To summarize,
wait() is called when a thread needs to suspend until another thread notifies it.
notify() wakes up one thread waiting to proceed.
notifyAll() wakes up all threads which are in waiting state.


15.Different States of the Java Thread What Are They Used For and How Does Transition Occur?
In Java, a thread goes through many states in its lifecycle. These states are essential for the control of the execution of a thread, enabling the JVM to trace and control the flow of the program. Here's a description of the different states a thread can be in and how it transitions from one state to another.
New:
When created, but has yet to run the state is described as being "New." Thus, during such a stage, the thread cannot be classified as active since it still hasn't become operational yet, it merely sits there waiting for a process of the CPU for its potential use.
Runnable:
Once started by calling the start() method, it enters the "Runnable" state. At this state, the thread is in a ready to run state but execution of the thread depends upon the availability of CPU resources. The thread waits for the system to allocate the CPU time for it.
Blocked:
A thread is said to enter the "Blocked" state if it is attempting to access a resource (read from a file, database or network) and the resource happens to be not available at the moment. It stays blocked till the resource is available.
Waiting:
A thread is said to be in the "Waiting" state if it is waiting for another thread to do some action, like releasing a lock or completing some task. The waiting period can be indefinite and the thread will be in this state until some other thread notifies it, generally by using methods like wait() or join().
Timed Waiting:
The "Timed Waiting" state makes the thread wait for a specific period of time to elapse. It gets there when methods such as sleep() or join() with a timeout are invoked. At the expiration of the stipulated time, the thread resumes in the Runnable state to resume its execution or takes another action.
Terminated:
A thread goes to the "Terminated" state when it is done with the work it is supposed to perform or has been terminated explicitly. This is a final state of a thread's lifecycle and there is no more execution of it.
Thread State Transitions:
Threads transition among states based on some action or condition.
New to Runnable: When you call the start() method on a thread, then it transitions from the "New" state to the "Runnable" state.
Runnable to Blocked: When a thread tries to access a resource and it's not available, it moves into the "Blocked" state. It will go back to the "Runnable" state when the resource is available.
Runnable to Waiting or Timed Waiting: A thread enters these states when it calls methods like wait(), sleep(), or join() with a timeout. It will go back to "Runnable" once the conditions it's waiting for are met.
Any state to Terminated: A thread moves to the "Terminated" state when it completes its execution, or if it is explicitly stopped.
For example:
Thread t = new Thread();
t.start(); /* Thread transitions from New to Runnable state */
In this case, when the start() method is called on this thread, the state shifts from "New" to "Runnable," waiting for an instance of CPU time to run. The thread will move through these states based on the availability of resources the actions taken by the thread and system conditions.