Multithreading allows multiple threads to run concurrently, improving the performance of applications. Understanding how to manage threads and handle synchronization is crucial for building efficient Java applications.
For more information on multithreading and concurrency, refer to our article: Multithreading and Concurrency.
A thread is a lightweight process that can run concurrently with other threads.
You can create a thread by extending the Thread
class or implementing the Runnable
interface.
class MyThread extends Thread {
public void run() {
System.out.println("Thread is running");
}
}
MyThread t = new MyThread();
t.start();
Runnable
and Thread
?Runnable
is an interface that can be implemented by any class, while Thread
is a class that can be extended.
start()
method?The start()
method is used to begin the execution of a thread.
run()
method?The run()
method contains the code that is executed when the thread is started.
sleep()
method?The sleep()
method pauses the execution of the current thread for a specified time.
try {
Thread.sleep(1000); // Sleep for 1 second
} catch (InterruptedException e) {
e.printStackTrace();
}
Thread priority is a value that determines the order in which threads are scheduled for execution.
You can set thread priority using the setPriority()
method.
Thread t = new Thread();
t.setPriority(Thread.MAX_PRIORITY);
Synchronization is a mechanism that ensures that only one thread can access a resource at a time.
You can synchronize a method by using the synchronized
keyword.
public synchronized void synchronizedMethod() {
// synchronized code
}
A synchronized block is a block of code that can only be accessed by one thread at a time.
public void method() {
synchronized(this) {
// synchronized code
}
}
A deadlock is a situation where two or more threads are blocked forever, waiting for each other.
You can prevent deadlock by ensuring that all threads acquire locks in a consistent order.
join()
method?The join()
method allows one thread to wait for the completion of another thread.
Thread t = new Thread();
t.start();
t.join(); // Wait for t to finish
yield()
method?The yield()
method is a hint to the thread scheduler that the current thread is willing to yield its current use of the CPU.
interrupt()
method?The interrupt()
method is used to interrupt a thread that is in a waiting or sleeping state.
volatile
keyword?The volatile
keyword indicates that a variable's value will be modified by different threads.
ThreadLocal
class?The ThreadLocal
class provides thread-local variables that are accessible only by the thread that created them.
The Executor framework provides a higher-level replacement for managing threads and thread pools.
You can create a thread pool using the Executors.newFixedThreadPool()
method.
ExecutorService executor = Executors.newFixedThreadPool(10);
A Callable
is similar to a Runnable
but can return a result and throw a checked exception.
You can submit a task using the submit()
method.
Future<String> future = executor.submit(new Callable<>() {
public String call() {
return "Task completed";
}
});
A Future
represents the result of an asynchronous computation.
You can retrieve the result using the get()
method.
String result = future.get();
A CountDownLatch
is a synchronization aid that allows one or more threads to wait until a set of operations being performed in other threads completes.
You can use a CountDownLatch
by initializing it with a count and calling countDown()
in the threads that complete their tasks.
CountDownLatch latch = new CountDownLatch(3);
// In worker threads
latch.countDown();
A CyclicBarrier
is a synchronization aid that allows a set of threads to all wait for each other to reach a common barrier point.
You can use a CyclicBarrier
by initializing it with a number of parties and calling await()
in each thread.
CyclicBarrier barrier = new CyclicBarrier(3);
// In worker threads
barrier.await();
A Semaphore
is a counting semaphore that can be used to control access to a resource by multiple threads.
You can use a Semaphore
by initializing it with a number of permits and calling acquire()
and release()
.
Semaphore semaphore = new Semaphore(1);
semaphore.acquire();
// critical section
semaphore.release();
The Fork/Join framework is designed to take advantage of multiple processors by breaking tasks into smaller subtasks.
A RecursiveTask
is a type of ForkJoinTask
that returns a result.
A RecursiveAction
is a type of ForkJoinTask
that does not return a result.
You can use the Fork/Join framework by creating a ForkJoinPool
and invoking tasks.
ForkJoinPool pool = new ForkJoinPool();
pool.invoke(new MyRecursiveTask());
wait()
and sleep()
?wait()
releases the lock and waits for a notification, while sleep()
does not release the lock.
notify()
method?The notify()
method wakes up a single thread that is waiting on the object's monitor.
notifyAll()
method?The notifyAll()
method wakes up all threads that are waiting on the object's monitor.
A thread is a lightweight process that shares the same memory space, while a process has its own memory space.
Thread safety is a property of a program that guarantees safe execution by multiple threads without unintended interactions.
You can achieve thread safety by using synchronization, locks, or concurrent collections.
A ReentrantLock
is a lock that allows a thread to enter a lock it already holds.
You can use a ReentrantLock
by creating an instance and using lock()
and unlock()
methods.
ReentrantLock lock = new ReentrantLock();
lock.lock();
try {
// critical section
} finally {
lock.unlock();
}
A ReadWriteLock
allows multiple threads to read or one thread to write, providing better concurrency.
You can use a ReadWriteLock
by creating an instance and using readLock()
and writeLock()
.
ReadWriteLock rwLock = new ReentrantReadWriteLock();
rwLock.readLock().lock();
try {
// read operation
} finally {
rwLock.readLock().unlock();
}
Thread.sleep()
method used for?The Thread.sleep()
method is used to pause the execution of the current thread for a specified duration.
Thread.interrupt()
method used for?The Thread.interrupt()
method is used to interrupt a thread that is in a waiting or sleeping state.
Thread.isAlive()
method?The Thread.isAlive()
method checks if a thread has been started and has not yet died.
Thread.getName()
method?The Thread.getName()
method returns the name of the thread.
Thread.setName()
method?The Thread.setName()
method sets the name of the thread.
ThreadGroup
class?The ThreadGroup
class is used to group multiple threads into a single group for easier management.