Resilience
resilience1CircuitBreaker
- Path
- pkg18resiliencepatterns/resilience1CircuitBreaker.java
- Package
- pkg18resiliencepatterns
- Study order
- 1
- Run
- Single-file source launch
- Command
- java pkg18resiliencepatterns/resilience1CircuitBreaker.java
- Lesson
- Back to the chapter
There is no in-browser runner. This is the file from the curriculum, unchanged.
1package pkg18resiliencepatterns;2 3import java.time.Duration;4import java.util.concurrent.atomic.AtomicInteger;5import java.util.function.Supplier;6 7/*8 * resilience1CircuitBreaker.java9 * --------------------------------10 * Circuit breaker: stop calling a failing dependency until it recovers.11 *12 * DEFINITION:13 * States: CLOSED (normal) -> OPEN (fail fast) -> HALF_OPEN (probe) -> CLOSED/OPEN.14 * Prevents cascading failures and wasted resources on a dead service.15 *16 * KEY POINTS:17 * - Trip to OPEN after failure threshold in a window.18 * - After cooldown, allow one probe (HALF_OPEN); success closes, failure reopens.19 * - Production: Resilience4j, Spring Cloud Circuit Breaker.20 */21public class resilience1CircuitBreaker {22 23 enum State { CLOSED, OPEN, HALF_OPEN }24 25 static class CircuitBreaker {26 private final int failureThreshold;27 private final long cooldownMs;28 private State state = State.CLOSED;29 private int failures = 0;30 private long openedAt = 0;31 32 CircuitBreaker(int failureThreshold, long cooldownMs) {33 this.failureThreshold = failureThreshold;34 this.cooldownMs = cooldownMs;35 }36 37 <T> T execute(Supplier<T> call) {38 if (state == State.OPEN) {39 if (System.currentTimeMillis() - openedAt >= cooldownMs) {40 state = State.HALF_OPEN;41 System.out.println(" breaker -> HALF_OPEN (probe)");42 } else {43 throw new RuntimeException("Circuit OPEN — fail fast");44 }45 }46 try {47 T result = call.get();48 onSuccess();49 return result;50 } catch (RuntimeException e) {51 onFailure();52 throw e;53 }54 }55 56 private void onSuccess() {57 failures = 0;58 if (state != State.CLOSED) {59 state = State.CLOSED;60 System.out.println(" breaker -> CLOSED");61 }62 }63 64 private void onFailure() {65 failures++;66 if (state == State.HALF_OPEN || failures >= failureThreshold) {67 state = State.OPEN;68 openedAt = System.currentTimeMillis();69 System.out.println(" breaker -> OPEN (failures=" + failures + ")");70 failures = 0;71 }72 }73 }74 75 public static void main(String[] args) throws InterruptedException {76 AtomicInteger attempts = new AtomicInteger();77 CircuitBreaker breaker = new CircuitBreaker(2, 500);78 Supplier<String> flaky = () -> {79 attempts.incrementAndGet();80 throw new RuntimeException("service down");81 };82 83 for (int i = 1; i <= 5; i++) {84 try {85 breaker.execute(flaky);86 } catch (RuntimeException e) {87 System.out.println("call " + i + ": " + e.getMessage());88 }89 Thread.sleep(150);90 }91 System.out.println("Total attempts to flaky service: " + attempts.get() + " (breaker limited calls)");92 }93}