1. The Hook (The "Byte-Sized" Intro)
- In a Nutshell: Functional patterns leverage lambdas/streams (function composition, monads). Concurrency patterns manage threads (Thread Pool, Producer-Consumer, Future). Reactive patterns handle async data streams (backpressure, event-driven).
- Benefits: Concise code (functional), scalability (concurrency), responsiveness (reactive).
- Use: Functional for data transformation, Concurrency for parallel execution, Reactive for event-driven systems!
Functional = assembly line transformations (process data step-by-step). Concurrency = restaurant kitchen (multiple chefs work in parallel). Reactive = streaming service (handle buffering, backpressure when network slow)!
2. Conceptual Clarity (The "Simple" Tier)
💡 The Analogy
- Function Composition: Pipeline (input → transform → transform → output)
- Thread Pool: Worker team (assign tasks to available workers)
- Reactive: Netflix streaming (adapt to network speed)
3. Technical Mastery (The "Deep Dive")
java
// ===========================================
// 1. FUNCTIONAL PATTERNS
// ===========================================
// Function Composition
import java.util.function.*;
class FunctionalPatterns {
static void demonstrateFunctionComposition() {
// Combine functions
Function<Integer, Integer> multiplyBy2 = x -> x * 2;
Function<Integer, Integer> add10 = x -> x + 10;
// Compose: add10(multiplyBy2(x))
Function<Integer, Integer> composed = multiplyBy2.andThen(add10);
System.out.println(composed.apply(5)); // (5 * 2) + 10 = 20
}
// Monad pattern (Optional)
static void demonstrateMonad() {
Optional<String> name = Optional.of("Alice");
String result = name
.map(String::toUpperCase)
.map(s -> "Hello, " + s)
.orElse("Unknown");
System.out.println(result); // Hello, ALICE
}
// Lazy evaluation
static void demonstrateLazyEvaluation() {
Supplier<String> lazy = () -> {
System.out.println("Computing...");
return "Result";
};
// Not computed yet!
System.out.println(lazy.get()); // NOW computed
}
}
// ===========================================
// 2. CONCURRENCY PATTERNS
// ===========================================
import java.util.concurrent.*;
// Thread Pool Pattern
class ThreadPoolDemo {
static void demonstrateThreadPool() throws Exception {
ExecutorService executor = Executors.newFixedThreadPool(3);
for (int i = 0; i < 10; i++) {
final int taskId = i;
executor.submit(() -> {
System.out.println("Task " + taskId + " by " +
Thread.currentThread().getName());
});
}
executor.shutdown();
executor.awaitTermination(1, TimeUnit.MINUTES);
}
}
// Producer-Consumer Pattern
class ProducerConsumerDemo {
static void demonstrate() throws Exception {
BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(10);
// Producer
Thread producer = new Thread(() -> {
try {
for (int i = 0; i < 20; i++) {
queue.put(i);
System.out.println("Produced: " + i);
Thread.sleep(100);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
// Consumer
Thread consumer = new Thread(() -> {
try {
while (true) {
Integer item = queue.take();
System.out.println("Consumed: " + item);
Thread.sleep(200);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
producer.start();
consumer.start();
}
}
// Future Pattern
class FutureDemo {
static void demonstrateFuture() throws Exception {
ExecutorService executor = Executors.newSingleThreadExecutor();
// Submit async task
Future<Integer> future = executor.submit(() -> {
Thread.sleep(1000);
return 42;
});
System.out.println("Doing other work...");
// Get result (blocks if not ready)
Integer result = future.get();
System.out.println("Result: " + result);
executor.shutdown();
}
// CompletableFuture (modern)
static void demonstrateCompletableFuture() {
CompletableFuture
.supplyAsync(() -> {
// Async computation
return "Hello";
})
.thenApply(s -> s + " World")
.thenAccept(System.out::println)
.join(); // Wait for completion
}
}
// ===========================================
// 3. REACTIVE PATTERNS
// ===========================================
// Simple reactive stream (conceptual)
interface Publisher<T> {
void subscribe(Subscriber<T> subscriber);
}
interface Subscriber<T> {
void onNext(T item);
void onComplete();
void onError(Throwable error);
}
// Example: Event stream with backpressure
class EventStreamDemo {
static void demonstrate() {
// Using Java 9+ Flow API
SubmissionPublisher<Integer> publisher = new SubmissionPublisher<>();
Flow.Subscriber<Integer> subscriber = new Flow.Subscriber<>() {
private Flow.Subscription subscription;
public void onSubscribe(Flow.Subscription subscription) {
this.subscription = subscription;
subscription.request(1); // Backpressure: request 1 item
}
public void onNext(Integer item) {
System.out.println("Received: " + item);
subscription.request(1); // Request next item
}
public void onComplete() {
System.out.println("Completed");
}
public void onError(Throwable error) {
error.printStackTrace();
}
};
publisher.subscribe(subscriber);
// Publish items
for (int i = 0; i < 10; i++) {
publisher.submit(i);
}
publisher.close();
}
}5. The Comparison & Decision Layer
| Pattern Type | Use When |
|---|---|
| Functional | Data transformation, pipeline processing |
| Concurrency | Parallel execution, resource sharing |
| Reactive | Event-driven systems, async data streams |
6. The "Interview Corner" (The Edge)
The "Killer" Interview Question: "Explain backpressure in reactive streams." Answer: Consumer controls flow!
java
// Without backpressure: Publisher overwhelms slow consumer
publisher.emit(1000000); // ❌ Consumer can't keep up!
// With backpressure: Consumer requests items
subscription.request(10); // ✅ "Send me 10 items"
// Process 10 items...
subscription.request(10); // Request 10 more
// Consumer controls rate, prevents overwhelming!Pro-Tip: CompletableFuture chaining:
java
CompletableFuture
.supplyAsync(() -> getUserId())
.thenApply(id -> fetchUserData(id))
.thenApply(data -> processData(data))
.thenAccept(result -> saveResult(result))
.exceptionally(ex -> {
handleError(ex);
return null;
});
// Non-blocking async pipeline!