diff --git a/core-java-modules/core-java-concurrency-basic-3/pom.xml b/core-java-modules/core-java-concurrency-basic-3/pom.xml
index 7771d1200c..7289877550 100644
--- a/core-java-modules/core-java-concurrency-basic-3/pom.xml
+++ b/core-java-modules/core-java-concurrency-basic-3/pom.xml
@@ -24,4 +24,16 @@
+
+ 4.2.0
+
+
+
+
+ org.awaitility
+ awaitility
+ ${awaitility.version}
+ test
+
+
\ No newline at end of file
diff --git a/core-java-modules/core-java-concurrency-basic-3/src/main/java/com/baeldung/concurrent/RequestProcessor.java b/core-java-modules/core-java-concurrency-basic-3/src/main/java/com/baeldung/concurrent/RequestProcessor.java
new file mode 100644
index 0000000000..9557a27f2a
--- /dev/null
+++ b/core-java-modules/core-java-concurrency-basic-3/src/main/java/com/baeldung/concurrent/RequestProcessor.java
@@ -0,0 +1,35 @@
+package com.baeldung.concurrent;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Random;
+import java.util.UUID;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+public class RequestProcessor {
+
+ private Map requestStatuses = new HashMap<>();
+
+ public String processRequest() {
+ String requestId = UUID.randomUUID().toString();
+ requestStatuses.put(requestId, "PROCESSING");
+
+ ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
+ executorService.schedule((() -> {
+ requestStatuses.put(requestId, "DONE");
+ }), getRandomNumberBetween(500, 2000), TimeUnit.MILLISECONDS);
+
+ return requestId;
+ }
+
+ public String getStatus(String requestId) {
+ return requestStatuses.get(requestId);
+ }
+
+ private int getRandomNumberBetween(int min, int max) {
+ Random random = new Random();
+ return random.nextInt(max - min) + min;
+ }
+}
diff --git a/core-java-modules/core-java-concurrency-basic-3/src/test/java/com/baeldung/concurrent/RequestProcessorUnitTest.java b/core-java-modules/core-java-concurrency-basic-3/src/test/java/com/baeldung/concurrent/RequestProcessorUnitTest.java
new file mode 100644
index 0000000000..c437b08b34
--- /dev/null
+++ b/core-java-modules/core-java-concurrency-basic-3/src/test/java/com/baeldung/concurrent/RequestProcessorUnitTest.java
@@ -0,0 +1,41 @@
+package com.baeldung.concurrent;
+
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.not;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.util.concurrent.TimeUnit;
+
+import org.awaitility.Awaitility;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+@DisplayName("Request processor")
+public class RequestProcessorUnitTest {
+
+ RequestProcessor requestProcessor = new RequestProcessor();
+
+ @Test
+ @DisplayName("Wait for completion using Thread.sleep")
+ void whenWaitingWithThreadSleep_thenStatusIsDone() throws InterruptedException {
+ String requestId = requestProcessor.processRequest();
+
+ Thread.sleep(2000);
+
+ assertEquals("DONE", requestProcessor.getStatus(requestId));
+ }
+
+ @Test
+ @DisplayName("Wait for completion using Awaitility")
+ void whenWaitingWithAwaitility_thenStatusIsDone() {
+ String requestId = requestProcessor.processRequest();
+
+ Awaitility.await()
+ .atMost(2, TimeUnit.SECONDS)
+ .pollDelay(500, TimeUnit.MILLISECONDS)
+ .until(() -> requestProcessor.getStatus(requestId), not(equalTo("PROCESSING")));
+
+ assertEquals("DONE", requestProcessor.getStatus(requestId));
+ }
+
+}