From 5d157d62c760e7ac246a86b510595912b013a800 Mon Sep 17 00:00:00 2001 From: HY-love-sleep <583699747@qq.com> Date: Sat, 3 May 2025 11:12:47 +0800 Subject: [PATCH 1/4] refactor: Refactor Task execution to support asynchronous callbacks --- .../src/main/java/com/iluwatar/callback/App.java | 3 ++- .../src/main/java/com/iluwatar/callback/Task.java | 12 ++++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/callback/src/main/java/com/iluwatar/callback/App.java b/callback/src/main/java/com/iluwatar/callback/App.java index 7b630f8da247..37f307b0e3e2 100644 --- a/callback/src/main/java/com/iluwatar/callback/App.java +++ b/callback/src/main/java/com/iluwatar/callback/App.java @@ -37,8 +37,9 @@ public final class App { private App() {} /** Program entry point. */ - public static void main(final String[] args) { + public static void main(final String[] args) throws InterruptedException { var task = new SimpleTask(); task.executeWith(() -> LOGGER.info("I'm done now.")); + Thread.sleep(3000); } } diff --git a/callback/src/main/java/com/iluwatar/callback/Task.java b/callback/src/main/java/com/iluwatar/callback/Task.java index d69697454dff..fd933d5ad558 100644 --- a/callback/src/main/java/com/iluwatar/callback/Task.java +++ b/callback/src/main/java/com/iluwatar/callback/Task.java @@ -24,15 +24,19 @@ */ package com.iluwatar.callback; -import java.util.Optional; +import java.util.concurrent.CompletableFuture; /** Template-method class for callback hook execution. */ public abstract class Task { - /** Execute with callback. */ + /** Execute the task and asynchronously call the callback method upon completion.*/ final void executeWith(Callback callback) { - execute(); - Optional.ofNullable(callback).ifPresent(Callback::call); + CompletableFuture.runAsync(() -> { + execute(); + if (callback != null) { + callback.call(); + } + }); } public abstract void execute(); From b42dc282591af6cb71931345d43f4666ebe16534 Mon Sep 17 00:00:00 2001 From: HY-love-sleep <583699747@qq.com> Date: Sat, 3 May 2025 11:31:56 +0800 Subject: [PATCH 2/4] fix: CallbackTest --- .../com/iluwatar/callback/CallbackTest.java | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/callback/src/test/java/com/iluwatar/callback/CallbackTest.java b/callback/src/test/java/com/iluwatar/callback/CallbackTest.java index 99939d491f4e..2bbe224d11d4 100644 --- a/callback/src/test/java/com/iluwatar/callback/CallbackTest.java +++ b/callback/src/test/java/com/iluwatar/callback/CallbackTest.java @@ -27,6 +27,8 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.api.Test; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; /** * Add a field as a counter. Every time the callback method is called increment this field. Unit @@ -39,19 +41,30 @@ class CallbackTest { private Integer callingCount = 0; @Test - void test() { - Callback callback = () -> callingCount++; + void test() throws InterruptedException { + CountDownLatch latch = new CountDownLatch(1); - var task = new SimpleTask(); + CountDownLatch finalLatch = latch; + Callback callback = () -> { + callingCount++; + finalLatch.countDown(); + }; - assertEquals(Integer.valueOf(0), callingCount, "Initial calling count of 0"); + var task = new SimpleTask(); task.executeWith(callback); + latch.await(5, TimeUnit.SECONDS); + assertEquals(Integer.valueOf(1), callingCount, "Callback called once"); + callingCount = 0; + latch = new CountDownLatch(1); + task.executeWith(callback); - assertEquals(Integer.valueOf(2), callingCount, "Callback called twice"); + latch.await(5, TimeUnit.SECONDS); + + assertEquals(Integer.valueOf(1), callingCount, "Callback called once again"); } } From 12a7f1d5d52bee30b13c7d2ba310bc37d6dfee6e Mon Sep 17 00:00:00 2001 From: HY-love-sleep <583699747@qq.com> Date: Sat, 3 May 2025 11:36:36 +0800 Subject: [PATCH 3/4] chore: code style --- .../src/main/java/com/iluwatar/callback/Task.java | 15 ++++++++------- .../java/com/iluwatar/callback/CallbackTest.java | 11 ++++++----- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/callback/src/main/java/com/iluwatar/callback/Task.java b/callback/src/main/java/com/iluwatar/callback/Task.java index fd933d5ad558..5d968ef5aa03 100644 --- a/callback/src/main/java/com/iluwatar/callback/Task.java +++ b/callback/src/main/java/com/iluwatar/callback/Task.java @@ -29,14 +29,15 @@ /** Template-method class for callback hook execution. */ public abstract class Task { - /** Execute the task and asynchronously call the callback method upon completion.*/ + /** Execute the task and asynchronously call the callback method upon completion. */ final void executeWith(Callback callback) { - CompletableFuture.runAsync(() -> { - execute(); - if (callback != null) { - callback.call(); - } - }); + CompletableFuture.runAsync( + () -> { + execute(); + if (callback != null) { + callback.call(); + } + }); } public abstract void execute(); diff --git a/callback/src/test/java/com/iluwatar/callback/CallbackTest.java b/callback/src/test/java/com/iluwatar/callback/CallbackTest.java index 2bbe224d11d4..d25a010a752e 100644 --- a/callback/src/test/java/com/iluwatar/callback/CallbackTest.java +++ b/callback/src/test/java/com/iluwatar/callback/CallbackTest.java @@ -26,9 +26,9 @@ import static org.junit.jupiter.api.Assertions.assertEquals; -import org.junit.jupiter.api.Test; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; +import org.junit.jupiter.api.Test; /** * Add a field as a counter. Every time the callback method is called increment this field. Unit @@ -45,10 +45,11 @@ void test() throws InterruptedException { CountDownLatch latch = new CountDownLatch(1); CountDownLatch finalLatch = latch; - Callback callback = () -> { - callingCount++; - finalLatch.countDown(); - }; + Callback callback = + () -> { + callingCount++; + finalLatch.countDown(); + }; var task = new SimpleTask(); From a86c211b4c2c7bbffb978fdd14ad33e26ffedb41 Mon Sep 17 00:00:00 2001 From: HY-love-sleep <583699747@qq.com> Date: Sat, 17 May 2025 17:36:02 +0800 Subject: [PATCH 4/4] feat: display synchronous and asynchronous callbacks --- .../main/java/com/iluwatar/callback/App.java | 10 +++- .../java/com/iluwatar/callback/Callback.java | 1 + .../main/java/com/iluwatar/callback/Task.java | 22 ++++++-- .../com/iluwatar/callback/CallbackTest.java | 56 ++++++++++++------- 4 files changed, 59 insertions(+), 30 deletions(-) diff --git a/callback/src/main/java/com/iluwatar/callback/App.java b/callback/src/main/java/com/iluwatar/callback/App.java index 37f307b0e3e2..9afaa3fc33fa 100644 --- a/callback/src/main/java/com/iluwatar/callback/App.java +++ b/callback/src/main/java/com/iluwatar/callback/App.java @@ -37,9 +37,13 @@ public final class App { private App() {} /** Program entry point. */ - public static void main(final String[] args) throws InterruptedException { + public static void main(final String[] args) { var task = new SimpleTask(); - task.executeWith(() -> LOGGER.info("I'm done now.")); - Thread.sleep(3000); + + LOGGER.info("=== Synchronous callback ==="); + task.executeWith(() -> LOGGER.info("Sync callback executed.")); + + LOGGER.info("=== Asynchronous callback ==="); + task.executeAsyncWith(() -> LOGGER.info("Async callback executed.")).join(); } } diff --git a/callback/src/main/java/com/iluwatar/callback/Callback.java b/callback/src/main/java/com/iluwatar/callback/Callback.java index 7b75b5c71077..67b2880e1681 100644 --- a/callback/src/main/java/com/iluwatar/callback/Callback.java +++ b/callback/src/main/java/com/iluwatar/callback/Callback.java @@ -25,6 +25,7 @@ package com.iluwatar.callback; /** Callback interface. */ +@FunctionalInterface public interface Callback { void call(); diff --git a/callback/src/main/java/com/iluwatar/callback/Task.java b/callback/src/main/java/com/iluwatar/callback/Task.java index 5d968ef5aa03..d58d55540f52 100644 --- a/callback/src/main/java/com/iluwatar/callback/Task.java +++ b/callback/src/main/java/com/iluwatar/callback/Task.java @@ -24,21 +24,31 @@ */ package com.iluwatar.callback; +import java.util.Optional; import java.util.concurrent.CompletableFuture; -/** Template-method class for callback hook execution. */ +/** + * Template-method class for callback hook execution. + * + *
Provides both synchronous and asynchronous execution with callback support.
+ */
public abstract class Task {
- /** Execute the task and asynchronously call the callback method upon completion. */
+ /** Execute the task and call the callback method synchronously upon completion. */
final void executeWith(Callback callback) {
- CompletableFuture.runAsync(
+ execute();
+ Optional.ofNullable(callback).ifPresent(Callback::call);
+ }
+
+ /** Execute the task and asynchronously call the callback method upon completion. */
+ final CompletableFuture