CountDownLatch – Coordinating Multiple Threads
CountDownLatch is a synchronizer that lets one or more threads pause until a set of operations running in other threads complete. The latch is initialized with a positive count; each worker thread invokes countDown() exactly once when it finishes, and the waiting thread calls await() to block until the counter reaches zero.
CountDownLatch doneSignal = new CountDownLatch(3);
Any thread that needs to wait simply executes:
doneSignal.await(); // blocks until counter == 0
Worker threads signal completion with:
doneSignal.countDown();
Complete Example
public class LatchDemo {
public static void main(String[] args) throws InterruptedException {
CountDownLatch latch = new CountDownLatch(3);
Runnable task = (name, sleep) -> () -> {
System.out.println(name + " started");
try {
Thread.sleep(sleep);
} catch (InterruptedException ignored) {
}
System.out.println(name + " finished");
latch.countDown();
};
new Thread(task.apply("Worker-A", 1000)).start();
new Thread(task.apply("Worker-B", 2000)).start();
new Thread(task.apply("Worker-C", 3000)).start();
latch.await();
System.out.println("All workers completed – main thread proceeds.");
}
}
Lambda Expressions in Java 8
A lambda is a concise way to implement a single-method interface (a functional interface). Syntax:
(parameters) -> expression
or
(parameters) -> { statements; }
Example: a two-argument addition function
BinaryOperator<Integer> add = (x, y) -> x + y;
int sum = add.apply(2, 3); // 5
Functional Interfaces
These are interfaces annotated with @FunctionalInterface and containing exactly one abstract method. Common ones supplied by java.util.function:
Runnable– no-arg, voidCallable<T>– no-arg, returns TConsumer<T>– takes T, returns voidSupplier<T>– no-arg, returns TFunction<T,R>– takes T, returns RPredicate<T>– takes T, returns booleanComparator<T>– compares two T instances
Function Example
Function<String, Integer> lengthFn = String::length;
int len = lengthFn.apply("Hello"); // 5
Comparator Example
class Person {
private final String name;
private final int age;
Person(String name, int age) {
this.name = name;
this.age = age;
}
public int getAge() { return age; }
public String toString() { return name + " (" + age + ")"; }
}
List<Person> people = List.of(
new Person("Alice", 25),
new Person("Bob", 20),
new Person("Charlie", 30)
);
people.sort(Comparator.comparingInt(Person::getAge));
people.forEach(System.out::println); // Bob (20), Alice (25), Charlie (30)
Predictae Example
Predicate<Integer> isEven = n -> n % 2 == 0;
System.out.println(isEven.test(4)); // true