Answer: A thread in Java goes through the following life cycle states:
- New: The thread is created but not yet started using the
newkeyword, e.g.,Thread t = new Thread();. At this stage, it is not scheduled for execution. - Runnable: Once the
start()method is invoked, the thread moves to the Runnable state. It is ready to run but waiting for the CPU scheduler to allocate time. - Running: When the thread is picked up by the thread scheduler, it enters the Running state and begins execution.
- Blocked/Waiting: The thread can move to a Blocked or Waiting state if it encounters conditions such as waiting for I/O operations or synchronization locks.
- Terminated: Once the thread completes its task or is explicitly stopped, it moves to the Terminated state and cannot be restarted.
Example:
Thread t = new Thread(() -> System.out.println("Thread running"));
t.start();Answer: Daemon threads are low-priority threads that provide background services to user threads. They automatically terminate when all non-daemon (user) threads have finished execution. Examples include garbage collection and other JVM maintenance tasks.
- Creating Daemon Threads: Use the
setDaemon(true)method before starting the thread.
Example:
Thread daemonThread = new Thread(() -> {
while (true) {
System.out.println("Daemon thread running");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
break;
}
}
});
daemonThread.setDaemon(true);
daemonThread.start();Answer:
The synchronized keyword ensures that only one thread can access a block of code or method at a time:
- Instance Methods: The lock is tied to the instance of the object.
- Static Methods: The lock is tied to the
Classobject.
Example:
class Example {
public synchronized void instanceMethod() {
System.out.println("Instance lock acquired");
}
public static synchronized void staticMethod() {
System.out.println("Class lock acquired");
}
}Answer:
Thread priorities are integers between Thread.MIN_PRIORITY (1) and Thread.MAX_PRIORITY (10). They act as hints to the thread scheduler about the importance of a thread. However, the actual execution depends on the JVM and operating system.
Example:
Thread t1 = new Thread(() -> System.out.println("Thread 1"));
t1.setPriority(Thread.MIN_PRIORITY);
Thread t2 = new Thread(() -> System.out.println("Thread 2"));
t2.setPriority(Thread.MAX_PRIORITY);
t1.start();
t2.start();Answer:
The join() method allows one thread to wait for the completion of another thread before proceeding. This ensures sequential execution when needed.
Example:
Thread t = new Thread(() -> System.out.println("Thread finished"));
t.start();
t.join();
System.out.println("Main thread continues after t completes");Answer:
- Runnable: A functional interface with a
run()method. It does not return any value or throw checked exceptions. - Callable: A functional interface with a
call()method. It can return a value and throw checked exceptions.
Example:
Callable<Integer> callable = () -> 42;
Runnable runnable = () -> System.out.println("Runnable running");
ExecutorService executor = Executors.newFixedThreadPool(2);
Future<Integer> future = executor.submit(callable);
executor.submit(runnable);
System.out.println("Callable result: " + future.get());
executor.shutdown();Answer:
ThreadLocal provides thread-local variables, where each thread accessing the variable has its own isolated copy. It is commonly used to maintain per-thread state, such as user sessions or transactions.
Example:
ThreadLocal<Integer> threadLocal = ThreadLocal.withInitial(() -> 0);
Thread t1 = new Thread(() -> {
threadLocal.set(100);
System.out.println("Thread 1 value: " + threadLocal.get());
});
Thread t2 = new Thread(() -> {
threadLocal.set(200);
System.out.println("Thread 2 value: " + threadLocal.get());
});
t1.start();
t2.start();Answer:
Java's java.util.concurrent package provides tools for efficient and thread-safe concurrency:
- Executor Framework: Manages thread pools.
- Concurrent Collections: e.g.,
ConcurrentHashMap,CopyOnWriteArrayList. - Locks: e.g.,
ReentrantLock. - Synchronizers: e.g.,
CountDownLatch,CyclicBarrier. - Atomic Variables: e.g.,
AtomicInteger,AtomicLong.
Example:
ExecutorService executor = Executors.newFixedThreadPool(2);
executor.submit(() -> System.out.println("Task executed"));
executor.shutdown();Answer:
ExecutorService simplifies thread management by providing a thread pool mechanism. It enables scheduling, submitting tasks, and managing thread lifecycle efficiently.
Example:
ExecutorService executor = Executors.newSingleThreadExecutor();
executor.submit(() -> System.out.println("Single-threaded task"));
executor.shutdown();Answer:
synchronized: Simple to use, handles locking automatically, but less flexible.ReentrantLock: Requires explicit locking and unlocking, supports advanced features like try-lock, interruptible locks, and fairness policies.
Example:
ReentrantLock lock = new ReentrantLock();
lock.lock();
try {
System.out.println("Critical section");
} finally {
lock.unlock();
}