synchronizedUsed to achieve thread safety by allowing only one thread to access a particular block of code or method at a time. It ensures that a critical section of code is not concurrently accessed by multiple threads.
public synchronized void method() {
// Critical section of code
}
// Or synchronized block
public void method() {
synchronized(this) {
// Critical section of code
}
}
volatileUsed to mark a variable as “volatile,” ensuring that every read of the variable will be directly from memory, and not from a cached copy. This helps in ensuring visibility of shared data between threads.
private volatile boolean flag = true;
public void stopThread() {
flag = false;
}
wait()A method called on a monitor object (typically within a synchronized block) to make the current thread release the lock (so other threads can use it) and go into a waiting state until another thread calls notify() or notifyAll() on the same object.
synchronized (lock) {
lock.wait(); // Current thread waits until notified
}
notify() and notifyAll()These methods are used to wake up threads that are waiting on a monitor object. notify() wakes up one waiting thread, while notifyAll() wakes up all waiting threads.
synchronized (lock) {
lock.notify(); // Wake up one waiting thread
}
Thread ClassThis class represents a thread in Java. You can create a new thread by extending the Thread class or by implementing the Runnable interface and passing it to a Thread object.
Thread classclass MyThread extends Thread {
public void run() {
// Code to be executed by the thread
}
}
MyThread thread = new MyThread();
thread.start(); // Start the thread
Runnable interfacepublic class CustomThreadRunnable implements Runnable {
@Override
public void run() {
System.out.println("Entered Custom Thread implementing Runnable's run method");
}
}
Runnable InterfaceUsed to create a thread by implementing the run() method. It allows for more flexibility as a class can implement Runnable and extend another class at the same time.
class MyRunnable implements Runnable {
public void run() {
// Code to be executed by the thread
}
}
Thread thread = new Thread(new MyRunnable());
thread.start(); // Start the thread
join()This method makes one thread wait for the completion of another thread.
When you call join() on a thread, the current thread will block until the thread on which join() was called finishes.
Thread thread = new Thread(() -> {
// Some work
});
thread.start();
thread.join(); // Wait for this thread to finish
sleep()Makes the current thread sleep for a specified duration of time (in milliseconds), causing it to temporarily cease execution.
But it still holds the lock while sleep unlike wait() if in synchronized block.
try {
Thread.sleep(1000); // Sleep for 1 second
} catch (InterruptedException e) {
e.printStackTrace();
}
yield()This method pauses the currently executing thread to allow other threads of the same priority to execute. It’s a suggestion to the thread scheduler that the current thread is willing to yield its current use of a CPU.
Thread.yield(); // Suggest to yield execution to other threads
ExecutorService and ExecutorsPart of the java.util.concurrent package, ExecutorService provides a higher-level replacement for working with threads. It manages thread pools and offers a cleaner and more efficient way to execute asynchronous tasks.
ExecutorService executor = Executors.newFixedThreadPool(10);
executor.submit(() -> {
// Task to be executed
});
executor.shutdown();
Callable and FutureCallable is similar to Runnable but can return a result.
Future represents the result of an asynchronous computation.
You can retrieve the result of a Callable using a Future.
Callable<Integer> callable = () -> {
return 123;
};
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<Integer> future = executor.submit(callable);
Integer result = future.get(); // Blocks until result is available
executor.shutdown();
ReentrantLockA more flexible and powerful locking mechanism compared to synchronized.
It allows for explicit lock management with features like fairness policies and the ability to interrupt threads waiting to acquire the lock.
ReentrantLock lock = new ReentrantLock();
lock.lock();
try {
// Critical section of code
} finally {
lock.unlock();
}
CountDownLatchA synchronization aid that allows one or more threads to wait until a set of operations being performed in other threads completes. It is used when you want to wait for multiple threads to complete before proceeding.
CountDownLatch latch = new CountDownLatch(3);
for (int i = 0; i < 3; i++) {
new Thread(() -> {
// Do some work
latch.countDown(); // Decrement the count
}).start();
}
latch.await(); // Wait for the count to reach zero