feat: Implement Thread-Pool Executor pattern (#3271)

- Add implementation of Thread-Pool Executor pattern using hotel front desk example
- Include unit tests
- Create detailed README with pattern explanation and examples
- Add Java source code with appropriate Javadoc comments

Closes #3226
This commit is contained in:
yoobin_mion
2025-05-16 03:53:37 +09:00
committed by GitHub
parent 3ac1a36b05
commit 8529017e02
13 changed files with 1041 additions and 0 deletions
@@ -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.
*
* <p>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.
*
* <p>Key benefits demonstrated:
*
* <ul>
* <li>Resource management - Limiting the number of concurrent threads
* <li>Efficiency - Reusing threads instead of creating new ones for each task
* <li>Responsiveness - Handling many requests with limited resources
* </ul>
*/
@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<Future<String>> vipResults = new ArrayList<>();
for (int i = 1; i <= 3; i++) {
Future<String> 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<String> 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.");
}
}
}
@@ -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<Void> 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 <T> the type of the task's result
* @return a Future representing pending completion of the task
*/
public <T> Future<T> submitVipGuestCheckIn(Callable<T> 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;
}
}
@@ -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);
}
}
@@ -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<String> {
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;
}
}
@@ -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[] {}));
}
}
@@ -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<String> task = () -> "VIP Check-in complete";
Future<String> 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<Future<?>> 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<Future<String>> vipResults = new ArrayList<>();
for (int i = 0; i < vipTaskCount; i++) {
final int guestNum = i;
Future<String> 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<String> result = vipResults.get(i);
assertTrue(result.isDone());
assertEquals("VIP-" + i + " checked in", result.get());
}
}
}
@@ -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<String> 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());
}
}
@@ -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);
}
}