diff --git a/throttling/README.md b/throttling/README.md index be47dd4a8..fc7525103 100644 --- a/throttling/README.md +++ b/throttling/README.md @@ -39,7 +39,6 @@ In this example a young human and an old dwarf walk into a bar. They start order `BarCustomer` class presents the clients of the `Bartender` API. `CallsCount` tracks the number of calls per `BarCustomer`. ```java - @Getter public class BarCustomer { @@ -55,7 +54,9 @@ public class BarCustomer { callsCount.addTenant(name); } } +``` +```java @Slf4j public final class CallsCount { private final Map tenantCallsCount = new ConcurrentHashMap<>(); @@ -85,7 +86,9 @@ Next, the service that the tenants are calling is introduced. To track the call public interface Throttler { void start(); } +``` +```java public class ThrottleTimerImpl implements Throttler { private final int throttlePeriod; @@ -142,36 +145,42 @@ class Bartender { Now it is possible to see the full example in action. `BarCustomer` young human is rate-limited to 2 calls per second and the old dwarf to 4. ```java -public static void main(String[] args) { - var callsCount = new CallsCount(); - var human = new BarCustomer("young human", 2, callsCount); - var dwarf = new BarCustomer("dwarf soldier", 4, callsCount); +@Slf4j +public class App { - var executorService = Executors.newFixedThreadPool(2); + public static void main(String[] args) { + var callsCount = new CallsCount(); + var human = new BarCustomer("young human", 2, callsCount); + var dwarf = new BarCustomer("dwarf soldier", 4, callsCount); - executorService.execute(() -> makeServiceCalls(human, callsCount)); - executorService.execute(() -> makeServiceCalls(dwarf, callsCount)); + var executorService = Executors.newFixedThreadPool(2); - executorService.shutdown(); - try { - executorService.awaitTermination(10, TimeUnit.SECONDS); - } catch (InterruptedException e) { - LOGGER.error("Executor service terminated: {}", e.getMessage()); - } -} + executorService.execute(() -> makeServiceCalls(human, callsCount)); + executorService.execute(() -> makeServiceCalls(dwarf, callsCount)); -private static void makeServiceCalls(BarCustomer barCustomer, CallsCount callsCount) { - var timer = new ThrottleTimerImpl(1000, callsCount); - var service = new Bartender(timer, callsCount); - // Sleep is introduced to keep the output in check and easy to view and analyze the results. - IntStream.range(0, 50).forEach(i -> { - service.orderDrink(barCustomer); + executorService.shutdown(); try { - Thread.sleep(100); + if (!executorService.awaitTermination(10, TimeUnit.SECONDS)) { + executorService.shutdownNow(); + } } catch (InterruptedException e) { - LOGGER.error("Thread interrupted: {}", e.getMessage()); + executorService.shutdownNow(); } - }); + } + + private static void makeServiceCalls(BarCustomer barCustomer, CallsCount callsCount) { + var timer = new ThrottleTimerImpl(1000, callsCount); + var service = new Bartender(timer, callsCount); + // Sleep is introduced to keep the output in check and easy to view and analyze the results. + IntStream.range(0, 50).forEach(i -> { + service.orderDrink(barCustomer); + try { + Thread.sleep(100); + } catch (InterruptedException e) { + LOGGER.error("Thread interrupted: {}", e.getMessage()); + } + }); + } } ``` @@ -202,10 +211,6 @@ An excerpt from the example's console output: 18:46:37.148 [pool-1-thread-2] ERROR com.iluwatar.throttling.Bartender - I'm sorry dwarf soldier, you've had enough for today! ``` -## Class diagram - -![Throttling](./etc/throttling_urm.png "Throttling pattern class diagram") - ## Applicability * You need to protect resources from being overwhelmed by too many requests. @@ -239,5 +244,5 @@ Trade-offs: ## Credits -* [Throttling pattern](https://docs.microsoft.com/en-us/azure/architecture/patterns/throttling) -* [Cloud Design Patterns: Prescriptive Architecture Guidance for Cloud Applications (Microsoft patterns & practices)](https://www.amazon.com/gp/product/B00ITGHBBS/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=B00ITGHBBS&linkId=12aacdd0cec04f372e7152689525631a) +* [Throttling pattern (Microsoft)](https://docs.microsoft.com/en-us/azure/architecture/patterns/throttling) +* [Cloud Design Patterns: Prescriptive Architecture Guidance for Cloud Applications](https://amzn.to/4dLvowg)