+ +shutdown(): void
+ +awaitTermination(timeout: long, unit: TimeUnit): boolean
+}
+
+class Task {
+ -id: int
+ -name: String
+ -processingTime: long
+ +Task(id: int, name: String, processingTime: long)
+ +run(): void
+ +call(): TaskResult
+}
+
+class TaskResult {
+ -taskId: int
+ -taskName: String
+ -executionTime: long
+ +TaskResult(taskId: int, taskName: String, executionTime: long)
+}
+
+class App {
+ +main(args: String[]): void
+ -executeRunnableTasks(poolManager: ThreadPoolManager): void
+ -executeCallableTasks(poolManager: ThreadPoolManager): void
+}
+
+ExecutorService <|-- ThreadPoolExecutor : implements
+Task ..|> Runnable : implements
+Task ..|> Callable : implements
+Task --> TaskResult : produces
+ThreadPoolManager --> ExecutorService : wraps
+App --> ThreadPoolManager : uses
+App --> Task : creates
+
+@enduml
\ No newline at end of file
diff --git a/thread-pool-executor/pom.xml b/thread-pool-executor/pom.xml
new file mode 100644
index 000000000000..f77cd92c67aa
--- /dev/null
+++ b/thread-pool-executor/pom.xml
@@ -0,0 +1,83 @@
+
+
+
+
+ 4.0.0
+
+
+ com.iluwatar
+ java-design-patterns
+ 1.26.0-SNAPSHOT
+
+
+ thread-pool-executor
+
+
+
+ org.slf4j
+ slf4j-api
+
+
+ ch.qos.logback
+ logback-classic
+
+
+ org.junit.jupiter
+ junit-jupiter-engine
+ test
+
+
+ org.mockito
+ mockito-core
+ test
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-assembly-plugin
+
+
+
+
+
+ com.iluwatar.threadpoolexecutor.App
+
+
+
+
+
+
+
+
+
diff --git a/thread-pool-executor/src/main/java/com/iluwatar/threadpoolexecutor/App.java b/thread-pool-executor/src/main/java/com/iluwatar/threadpoolexecutor/App.java
new file mode 100644
index 000000000000..0c1292b89c3a
--- /dev/null
+++ b/thread-pool-executor/src/main/java/com/iluwatar/threadpoolexecutor/App.java
@@ -0,0 +1,90 @@
+/*
+ * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
+ *
+ * The MIT License
+ * Copyright © 2014-2022 Ilkka Seppälä
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package com.iluwatar.threadpoolexecutor;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * The Thread-Pool Executor pattern demonstrates how a pool of worker threads can be used to execute
+ * tasks concurrently. This pattern is particularly useful in scenarios where you need to execute a
+ * large number of independent tasks and want to limit the number of threads used.
+ *
+ * In this example, a hotel front desk with a fixed number of employees processes guest
+ * check-ins. Each employee is represented by a thread, and each check-in is a task.
+ *
+ *
Key benefits demonstrated:
+ *
+ *
+ * - Resource management - Limiting the number of concurrent threads
+ *
- Efficiency - Reusing threads instead of creating new ones for each task
+ *
- Responsiveness - Handling many requests with limited resources
+ *
+ */
+@Slf4j
+public class App {
+
+ /**
+ * Program main entry point.
+ *
+ * @param args program runtime arguments
+ */
+ public static void main(String[] args) throws InterruptedException, ExecutionException {
+
+ FrontDeskService frontDesk = new FrontDeskService(5);
+ LOGGER.info("Hotel front desk operation started!");
+
+ LOGGER.info("Processing 30 regular guest check-ins...");
+ for (int i = 1; i <= 30; i++) {
+ frontDesk.submitGuestCheckIn(new GuestCheckInTask("Guest-" + i));
+ Thread.sleep(100);
+ }
+
+ LOGGER.info("Processing 3 VIP guest check-ins...");
+ List> vipResults = new ArrayList<>();
+
+ for (int i = 1; i <= 3; i++) {
+ Future result =
+ frontDesk.submitVipGuestCheckIn(new VipGuestCheckInTask("VIP-Guest-" + i));
+ vipResults.add(result);
+ }
+
+ frontDesk.shutdown();
+
+ if (frontDesk.awaitTermination(1, TimeUnit.HOURS)) {
+ LOGGER.info("VIP Check-in Results:");
+ for (Future result : vipResults) {
+ LOGGER.info(result.get());
+ }
+ LOGGER.info("All guests have been successfully checked in. Front desk is now closed.");
+ } else {
+ LOGGER.warn("Check-in timeout. Forcefully shutting down the front desk.");
+ }
+ }
+}
diff --git a/thread-pool-executor/src/main/java/com/iluwatar/threadpoolexecutor/FrontDeskService.java b/thread-pool-executor/src/main/java/com/iluwatar/threadpoolexecutor/FrontDeskService.java
new file mode 100644
index 000000000000..b80236ee5ecf
--- /dev/null
+++ b/thread-pool-executor/src/main/java/com/iluwatar/threadpoolexecutor/FrontDeskService.java
@@ -0,0 +1,108 @@
+/*
+ * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
+ *
+ * The MIT License
+ * Copyright © 2014-2022 Ilkka Seppälä
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package com.iluwatar.threadpoolexecutor;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * FrontDeskService represents the hotel's front desk with a fixed number of employees. This class
+ * demonstrates the Thread-Pool Executor pattern using Java's ExecutorService.
+ */
+@Slf4j
+public class FrontDeskService {
+
+ private final ExecutorService executorService;
+ private final int numberOfEmployees;
+
+ /**
+ * Creates a new front desk with the specified number of employees.
+ *
+ * @param numberOfEmployees the number of employees (threads) at the front desk
+ */
+ public FrontDeskService(int numberOfEmployees) {
+ this.numberOfEmployees = numberOfEmployees;
+ this.executorService = Executors.newFixedThreadPool(numberOfEmployees);
+ LOGGER.info("Front desk initialized with {} employees.", numberOfEmployees);
+ }
+
+ /**
+ * Submits a regular guest check-in task to an available employee.
+ *
+ * @param task the check-in task to submit
+ * @return a Future representing pending completion of the task
+ */
+ public Future submitGuestCheckIn(Runnable task) {
+ LOGGER.debug("Submitting regular guest check-in task");
+ return executorService.submit(task, null);
+ }
+
+ /**
+ * Submits a VIP guest check-in task to an available employee.
+ *
+ * @param task the VIP check-in task to submit
+ * @param the type of the task's result
+ * @return a Future representing pending completion of the task
+ */
+ public Future submitVipGuestCheckIn(Callable task) {
+ LOGGER.debug("Submitting VIP guest check-in task");
+ return executorService.submit(task);
+ }
+
+ /**
+ * Closes the front desk after all currently checked-in guests are processed. No new check-ins
+ * will be accepted.
+ */
+ public void shutdown() {
+ LOGGER.info("Front desk is closing - no new guests will be accepted.");
+ executorService.shutdown();
+ }
+
+ /**
+ * Waits for all check-in processes to complete or until timeout.
+ *
+ * @param timeout the maximum time to wait
+ * @param unit the time unit of the timeout argument
+ * @return true if all tasks completed, false if timeout elapsed
+ * @throws InterruptedException if interrupted while waiting
+ */
+ public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
+ LOGGER.info("Waiting for all check-ins to complete (max wait: {} {})", timeout, unit);
+ return executorService.awaitTermination(timeout, unit);
+ }
+
+ /**
+ * Gets the number of employees at the front desk.
+ *
+ * @return the number of employees
+ */
+ public int getNumberOfEmployees() {
+ return numberOfEmployees;
+ }
+}
diff --git a/thread-pool-executor/src/main/java/com/iluwatar/threadpoolexecutor/GuestCheckInTask.java b/thread-pool-executor/src/main/java/com/iluwatar/threadpoolexecutor/GuestCheckInTask.java
new file mode 100644
index 000000000000..d8a33fdfc8d2
--- /dev/null
+++ b/thread-pool-executor/src/main/java/com/iluwatar/threadpoolexecutor/GuestCheckInTask.java
@@ -0,0 +1,52 @@
+/*
+ * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
+ *
+ * The MIT License
+ * Copyright © 2014-2022 Ilkka Seppälä
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package com.iluwatar.threadpoolexecutor;
+
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * GuestCheckInTask represents a regular guest check-in process. Implements Runnable because it
+ * performs an action without returning a result.
+ */
+@Slf4j
+@AllArgsConstructor
+public class GuestCheckInTask implements Runnable {
+
+ private final String guestName;
+
+ @Override
+ public void run() {
+ String employeeName = Thread.currentThread().getName();
+ LOGGER.info("{} is checking in {}...", employeeName, guestName);
+ try {
+ Thread.sleep(2000);
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ LOGGER.error("Check-in for {} was interrupted", guestName);
+ }
+ LOGGER.info("{} has been successfully checked in!", guestName);
+ }
+}
diff --git a/thread-pool-executor/src/main/java/com/iluwatar/threadpoolexecutor/VipGuestCheckInTask.java b/thread-pool-executor/src/main/java/com/iluwatar/threadpoolexecutor/VipGuestCheckInTask.java
new file mode 100644
index 000000000000..3948c114f0d6
--- /dev/null
+++ b/thread-pool-executor/src/main/java/com/iluwatar/threadpoolexecutor/VipGuestCheckInTask.java
@@ -0,0 +1,52 @@
+/*
+ * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
+ *
+ * The MIT License
+ * Copyright © 2014-2022 Ilkka Seppälä
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package com.iluwatar.threadpoolexecutor;
+
+import java.util.concurrent.Callable;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * VipGuestCheckInTask represents a VIP guest check-in process. Implements Callable because it
+ * returns a result (check-in confirmation).
+ */
+@Slf4j
+@AllArgsConstructor
+public class VipGuestCheckInTask implements Callable {
+
+ private final String vipGuestName;
+
+ @Override
+ public String call() throws Exception {
+ String employeeName = Thread.currentThread().getName();
+ LOGGER.info("{} is checking in VIP guest {}...", employeeName, vipGuestName);
+
+ Thread.sleep(1000);
+
+ String result = vipGuestName + " has been successfully checked in!";
+ LOGGER.info("VIP check-in completed: {}", result);
+ return result;
+ }
+}
diff --git a/thread-pool-executor/src/test/java/com/iluwatar/threadpoolexecutor/AppTest.java b/thread-pool-executor/src/test/java/com/iluwatar/threadpoolexecutor/AppTest.java
new file mode 100644
index 000000000000..13e3a5beec3c
--- /dev/null
+++ b/thread-pool-executor/src/test/java/com/iluwatar/threadpoolexecutor/AppTest.java
@@ -0,0 +1,38 @@
+/*
+ * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
+ *
+ * The MIT License
+ * Copyright © 2014-2022 Ilkka Seppälä
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.iluwatar.threadpoolexecutor;
+
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+
+import org.junit.jupiter.api.Test;
+
+class AppTest {
+
+ @Test
+ void appStartsWithoutException() {
+ assertDoesNotThrow(() -> App.main(new String[] {}));
+ }
+}
diff --git a/thread-pool-executor/src/test/java/com/iluwatar/threadpoolexecutor/FrontDeskServiceTest.java b/thread-pool-executor/src/test/java/com/iluwatar/threadpoolexecutor/FrontDeskServiceTest.java
new file mode 100644
index 000000000000..8d0396bf0541
--- /dev/null
+++ b/thread-pool-executor/src/test/java/com/iluwatar/threadpoolexecutor/FrontDeskServiceTest.java
@@ -0,0 +1,248 @@
+/*
+ * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
+ *
+ * The MIT License
+ * Copyright © 2014-2022 Ilkka Seppälä
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package com.iluwatar.threadpoolexecutor;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Future;
+import java.util.concurrent.RejectedExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+import org.junit.jupiter.api.Test;
+
+class FrontDeskServiceTest {
+
+ /**
+ * Tests that the constructor correctly sets the number of employees (threads). This verifies the
+ * basic initialization of the thread pool.
+ */
+ @Test
+ void testConstructorSetsCorrectNumberOfEmployees() {
+ int expectedEmployees = 3;
+
+ FrontDeskService frontDesk = new FrontDeskService(expectedEmployees);
+
+ assertEquals(expectedEmployees, frontDesk.getNumberOfEmployees());
+ }
+
+ /**
+ * Tests that the submitGuestCheckIn method returns a non-null Future object. This verifies the
+ * basic task submission functionality.
+ */
+ @Test
+ void testSubmitGuestCheckInReturnsNonNullFuture() {
+ FrontDeskService frontDesk = new FrontDeskService(1);
+
+ Runnable task =
+ () -> {
+ // Task that completes quickly
+ };
+
+ Future> future = frontDesk.submitGuestCheckIn(task);
+
+ assertNotNull(future);
+ }
+
+ /**
+ * Tests that the submitVipGuestCheckIn method returns a non-null Future object. This verifies
+ * that tasks with return values can be submitted correctly.
+ */
+ @Test
+ void testSubmitVipGuestCheckInReturnsNonNullFuture() {
+ FrontDeskService frontDesk = new FrontDeskService(1);
+ Callable task = () -> "VIP Check-in complete";
+
+ Future future = frontDesk.submitVipGuestCheckIn(task);
+
+ assertNotNull(future);
+ }
+
+ /**
+ * Tests that the shutdown and awaitTermination methods work correctly. This verifies the basic
+ * shutdown functionality of the thread pool.
+ */
+ @Test
+ void testShutdownAndAwaitTermination() throws InterruptedException {
+ FrontDeskService frontDesk = new FrontDeskService(2);
+ CountDownLatch taskLatch = new CountDownLatch(1);
+
+ Runnable task = taskLatch::countDown;
+
+ frontDesk.submitGuestCheckIn(task);
+ frontDesk.shutdown();
+ boolean terminated = frontDesk.awaitTermination(1, TimeUnit.SECONDS);
+
+ assertTrue(terminated);
+ assertTrue(taskLatch.await(100, TimeUnit.MILLISECONDS));
+ }
+
+ /**
+ * Tests the thread pool's behavior under load with multiple tasks. This verifies that the thread
+ * pool limits concurrent execution to the number of threads, all submitted tasks are eventually
+ * completed, and threads are reused for multiple tasks.
+ */
+ @Test
+ void testMultipleTasksUnderLoad() throws InterruptedException {
+ FrontDeskService frontDesk = new FrontDeskService(2);
+ int taskCount = 10;
+ CountDownLatch tasksCompletedLatch = new CountDownLatch(taskCount);
+ AtomicInteger concurrentTasks = new AtomicInteger(0);
+ AtomicInteger maxConcurrentTasks = new AtomicInteger(0);
+
+ for (int i = 0; i < taskCount; i++) {
+ frontDesk.submitGuestCheckIn(
+ () -> {
+ try {
+ int current = concurrentTasks.incrementAndGet();
+ maxConcurrentTasks.updateAndGet(max -> Math.max(max, current));
+
+ Thread.sleep(100);
+
+ concurrentTasks.decrementAndGet();
+ tasksCompletedLatch.countDown();
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+ });
+ }
+
+ boolean allTasksCompleted = tasksCompletedLatch.await(2, TimeUnit.SECONDS);
+
+ frontDesk.shutdown();
+ frontDesk.awaitTermination(1, TimeUnit.SECONDS);
+
+ assertTrue(allTasksCompleted);
+ assertEquals(2, maxConcurrentTasks.get());
+ assertEquals(0, concurrentTasks.get());
+ }
+
+ /**
+ * Tests proper shutdown behavior under load. This verifies that after shutdown no new tasks are
+ * accepted, all previously submitted tasks are completed, and the executor terminates properly
+ * after all tasks complete.
+ */
+ @Test
+ void testProperShutdownUnderLoad() throws InterruptedException {
+ FrontDeskService frontDesk = new FrontDeskService(2);
+ int taskCount = 5;
+ CountDownLatch startedTasksLatch = new CountDownLatch(2);
+ CountDownLatch tasksCompletionLatch = new CountDownLatch(taskCount);
+
+ for (int i = 0; i < taskCount; i++) {
+ frontDesk.submitGuestCheckIn(
+ () -> {
+ try {
+ startedTasksLatch.countDown();
+ Thread.sleep(100);
+ tasksCompletionLatch.countDown();
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+ });
+ }
+
+ assertTrue(startedTasksLatch.await(1, TimeUnit.SECONDS));
+
+ frontDesk.shutdown();
+
+ assertThrows(
+ RejectedExecutionException.class,
+ () -> {
+ frontDesk.submitGuestCheckIn(() -> {});
+ });
+
+ boolean allTasksCompleted = tasksCompletionLatch.await(2, TimeUnit.SECONDS);
+
+ boolean terminated = frontDesk.awaitTermination(1, TimeUnit.SECONDS);
+
+ assertTrue(allTasksCompleted);
+ assertTrue(terminated);
+ }
+
+ /**
+ * Tests concurrent execution of different task types (regular and VIP). This verifies that both
+ * Runnable and Callable tasks can be processed concurrently, all tasks complete successfully, and
+ * Callable tasks return their results correctly.
+ */
+ @Test
+ void testConcurrentRegularAndVipTasks() throws Exception {
+ FrontDeskService frontDesk = new FrontDeskService(3);
+ int regularTaskCount = 4;
+ int vipTaskCount = 3;
+ CountDownLatch allTasksLatch = new CountDownLatch(regularTaskCount + vipTaskCount);
+
+ List> regularResults = new ArrayList<>();
+ for (int i = 0; i < regularTaskCount; i++) {
+ Future> result =
+ frontDesk.submitGuestCheckIn(
+ () -> {
+ try {
+ Thread.sleep(50);
+ allTasksLatch.countDown();
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+ });
+ regularResults.add(result);
+ }
+
+ List> vipResults = new ArrayList<>();
+ for (int i = 0; i < vipTaskCount; i++) {
+ final int guestNum = i;
+ Future result =
+ frontDesk.submitVipGuestCheckIn(
+ () -> {
+ Thread.sleep(25);
+ allTasksLatch.countDown();
+ return "VIP-" + guestNum + " checked in";
+ });
+ vipResults.add(result);
+ }
+
+ boolean allCompleted = allTasksLatch.await(2, TimeUnit.SECONDS);
+
+ frontDesk.shutdown();
+ frontDesk.awaitTermination(1, TimeUnit.SECONDS);
+
+ assertTrue(allCompleted);
+
+ for (Future> result : regularResults) {
+ assertTrue(result.isDone());
+ }
+
+ for (int i = 0; i < vipTaskCount; i++) {
+ Future result = vipResults.get(i);
+ assertTrue(result.isDone());
+ assertEquals("VIP-" + i + " checked in", result.get());
+ }
+ }
+}
diff --git a/thread-pool-executor/src/test/java/com/iluwatar/threadpoolexecutor/GuestCheckInTaskTest.java b/thread-pool-executor/src/test/java/com/iluwatar/threadpoolexecutor/GuestCheckInTaskTest.java
new file mode 100644
index 000000000000..27bb75efd2db
--- /dev/null
+++ b/thread-pool-executor/src/test/java/com/iluwatar/threadpoolexecutor/GuestCheckInTaskTest.java
@@ -0,0 +1,55 @@
+/*
+ * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
+ *
+ * The MIT License
+ * Copyright © 2014-2022 Ilkka Seppälä
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package com.iluwatar.threadpoolexecutor;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.util.concurrent.atomic.AtomicReference;
+import org.junit.jupiter.api.Test;
+
+class GuestCheckInTaskTest {
+
+ /**
+ * Tests that the task executes in the current thread when called directly. This verifies that the
+ * thread name inside the task matches the calling thread.
+ */
+ @Test
+ void testThreadNameInTask() {
+ String guestName = "TestGuest";
+ AtomicReference capturedThreadName = new AtomicReference<>();
+
+ GuestCheckInTask task =
+ new GuestCheckInTask(guestName) {
+ @Override
+ public void run() {
+ capturedThreadName.set(Thread.currentThread().getName());
+ }
+ };
+
+ task.run();
+
+ assertEquals(Thread.currentThread().getName(), capturedThreadName.get());
+ }
+}
diff --git a/thread-pool-executor/src/test/java/com/iluwatar/threadpoolexecutor/VipGuestCheckInTaskTest.java b/thread-pool-executor/src/test/java/com/iluwatar/threadpoolexecutor/VipGuestCheckInTaskTest.java
new file mode 100644
index 000000000000..d76d90625c95
--- /dev/null
+++ b/thread-pool-executor/src/test/java/com/iluwatar/threadpoolexecutor/VipGuestCheckInTaskTest.java
@@ -0,0 +1,48 @@
+/*
+ * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
+ *
+ * The MIT License
+ * Copyright © 2014-2022 Ilkka Seppälä
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package com.iluwatar.threadpoolexecutor;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+import org.junit.jupiter.api.Test;
+
+class VipGuestCheckInTaskTest {
+
+ /**
+ * Tests that the call method returns the expected result string. This verifies that the VIP
+ * check-in task correctly formats its result message.
+ */
+ @Test
+ void testCallReturnsExpectedResult() throws Exception {
+ String vipGuestName = "TestVipGuest";
+ VipGuestCheckInTask task = new VipGuestCheckInTask(vipGuestName);
+
+ String result = task.call();
+
+ assertNotNull(result);
+ assertEquals("TestVipGuest has been successfully checked in!", result);
+ }
+}