, consumer : Consumer) : Long {static}
+ }
+ class SquareNumberRequest {
+ - LOGGER : Logger {static}
+ - number : Long
+ + SquareNumberRequest(number : Long)
+ + delayedSquaring(consumer : Consumer)
+ }
+
+ object SquareNumberRequest1
+ object SquareNumberRequest2
+ object SquareNumberRequest3
+ diamond dia
+}
+
+App --> FanOutFanIn
+FanOutFanIn --> "fan out - running in parallel" SquareNumberRequest1
+FanOutFanIn --> "fan out" SquareNumberRequest2
+FanOutFanIn --> "fan out" SquareNumberRequest3
+SquareNumberRequest1 --> "fan in - aggregate using callback" dia
+SquareNumberRequest2 --> "fan in" dia
+SquareNumberRequest3 --> "fan in" dia
+dia --> Consumer
+@enduml
\ No newline at end of file
diff --git a/fanout-fanin/pom.xml b/fanout-fanin/pom.xml
new file mode 100644
index 000000000..382cc342e
--- /dev/null
+++ b/fanout-fanin/pom.xml
@@ -0,0 +1,69 @@
+
+
+
+
+ java-design-patterns
+ com.iluwatar
+ 1.25.0-SNAPSHOT
+
+ 4.0.0
+
+ fanout-fanin
+
+
+
+ org.junit.jupiter
+ junit-jupiter-engine
+ test
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-assembly-plugin
+
+
+
+
+
+ com.iluwatar.fanout.fanin.App
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/fanout-fanin/src/main/java/com/iluwatar/fanout/fanin/App.java b/fanout-fanin/src/main/java/com/iluwatar/fanout/fanin/App.java
new file mode 100644
index 000000000..cc70ff141
--- /dev/null
+++ b/fanout-fanin/src/main/java/com/iluwatar/fanout/fanin/App.java
@@ -0,0 +1,74 @@
+/*
+ * The MIT License
+ * Copyright © 2014-2021 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.fanout.fanin;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import lombok.extern.slf4j.Slf4j;
+
+
+
+/**
+ * FanOut/FanIn pattern is a concurrency pattern that refers to executing multiple instances of the
+ * activity function concurrently. The "fan out" part is essentially splitting the data into
+ * multiple chunks and then calling the activity function multiple times, passing the chunks.
+ *
+ * When each chunk has been processed, the "fan in" takes place that aggregates results from each
+ * instance of function and forms a single final result.
+ *
+ *
This pattern is only really useful if you can “chunk” the workload in a meaningful way for
+ * splitting up to be processed in parallel.
+ */
+@Slf4j
+public class App {
+
+ /**
+ * Entry point.
+ *
+ *
Implementation provided has a list of numbers that has to be squared and added. The list can
+ * be chunked in any way and the "activity function" {@link
+ * SquareNumberRequest#delayedSquaring(Consumer)} i.e. squaring the number ca be done
+ * concurrently. The "fan in" part is handled by the {@link Consumer} that takes in the result
+ * from each instance of activity and aggregates it whenever that particular activity function
+ * gets over.
+ */
+ public static void main(String[] args) {
+ final List numbers = Arrays.asList(1L, 3L, 4L, 7L, 8L);
+
+ LOGGER.info("Numbers to be squared and get sum --> {}", numbers);
+
+ final List requests =
+ numbers.stream().map(SquareNumberRequest::new).collect(Collectors.toList());
+
+ var consumer = new Consumer(0L);
+
+ // Pass the request and the consumer to fanOutFanIn or sometimes referred as Orchestrator
+ // function
+ final Long sumOfSquaredNumbers = FanOutFanIn.fanOutFanIn(requests, consumer);
+
+ LOGGER.info("Sum of all squared numbers --> {}", sumOfSquaredNumbers);
+ }
+}
diff --git a/fanout-fanin/src/main/java/com/iluwatar/fanout/fanin/Consumer.java b/fanout-fanin/src/main/java/com/iluwatar/fanout/fanin/Consumer.java
new file mode 100644
index 000000000..79e3445dc
--- /dev/null
+++ b/fanout-fanin/src/main/java/com/iluwatar/fanout/fanin/Consumer.java
@@ -0,0 +1,48 @@
+/*
+ * The MIT License
+ * Copyright © 2014-2021 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.fanout.fanin;
+
+import java.util.concurrent.atomic.AtomicLong;
+
+import lombok.Getter;
+
+
+
+/**
+ * Consumer or callback class that will be called everytime a request is complete This will
+ * aggregate individual result to form a final result.
+ */
+@Getter
+public class Consumer {
+
+ private final AtomicLong sumOfSquaredNumbers;
+
+ Consumer(Long init) {
+ sumOfSquaredNumbers = new AtomicLong(init);
+ }
+
+ public Long add(final Long num) {
+ return sumOfSquaredNumbers.addAndGet(num);
+ }
+}
diff --git a/fanout-fanin/src/main/java/com/iluwatar/fanout/fanin/FanOutFanIn.java b/fanout-fanin/src/main/java/com/iluwatar/fanout/fanin/FanOutFanIn.java
new file mode 100644
index 000000000..71af5ae9f
--- /dev/null
+++ b/fanout-fanin/src/main/java/com/iluwatar/fanout/fanin/FanOutFanIn.java
@@ -0,0 +1,62 @@
+/*
+ * The MIT License
+ * Copyright © 2014-2021 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.fanout.fanin;
+
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.stream.Collectors;
+
+/**
+ * FanOutFanIn class processes long running requests, when any of the processes gets over, result is
+ * passed over to the consumer or the callback function. Consumer will aggregate the results as they
+ * keep on completing.
+ */
+public class FanOutFanIn {
+
+ /**
+ * the main fanOutFanIn function or orchestrator function.
+ * @param requests List of numbers that need to be squared and summed up
+ * @param consumer Takes in the squared number from {@link SquareNumberRequest} and sums it up
+ * @return Aggregated sum of all squared numbers.
+ */
+ public static Long fanOutFanIn(
+ final List requests, final Consumer consumer) {
+
+ ExecutorService service = Executors.newFixedThreadPool(requests.size());
+
+ // fanning out
+ List> futures =
+ requests.stream()
+ .map(
+ request ->
+ CompletableFuture.runAsync(() -> request.delayedSquaring(consumer), service))
+ .collect(Collectors.toList());
+
+ CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
+
+ return consumer.getSumOfSquaredNumbers().get();
+ }
+}
diff --git a/fanout-fanin/src/main/java/com/iluwatar/fanout/fanin/SquareNumberRequest.java b/fanout-fanin/src/main/java/com/iluwatar/fanout/fanin/SquareNumberRequest.java
new file mode 100644
index 000000000..73db6ca87
--- /dev/null
+++ b/fanout-fanin/src/main/java/com/iluwatar/fanout/fanin/SquareNumberRequest.java
@@ -0,0 +1,63 @@
+/*
+ * The MIT License
+ * Copyright © 2014-2021 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.fanout.fanin;
+
+import java.security.SecureRandom;
+
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * Squares the number with a little timeout to give impression of long running process that return
+ * at different times.
+ */
+@Slf4j
+@AllArgsConstructor
+public class SquareNumberRequest {
+
+ private final Long number;
+
+ /**
+ * Squares the number with a little timeout to give impression of long running process that return
+ * at different times.
+ * @param consumer callback class that takes the result after the delay.
+ * */
+ public void delayedSquaring(final Consumer consumer) {
+
+ var minTimeOut = 5000L;
+
+ SecureRandom secureRandom = new SecureRandom();
+ var randomTimeOut = secureRandom.nextInt(2000);
+
+ try {
+ // this will make the thread sleep from 5-7s.
+ Thread.sleep(minTimeOut + randomTimeOut);
+ } catch (InterruptedException e) {
+ LOGGER.error("Exception while sleep ", e);
+ Thread.currentThread().interrupt();
+ } finally {
+ consumer.add(number * number);
+ }
+ }
+}
diff --git a/fanout-fanin/src/test/java/com/iluwatar/fanout/fanin/AppTest.java b/fanout-fanin/src/test/java/com/iluwatar/fanout/fanin/AppTest.java
new file mode 100644
index 000000000..d221066e2
--- /dev/null
+++ b/fanout-fanin/src/test/java/com/iluwatar/fanout/fanin/AppTest.java
@@ -0,0 +1,36 @@
+/*
+ * The MIT License
+ * Copyright © 2014-2021 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.fanout.fanin;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+
+class AppTest {
+
+ @Test
+ void shouldLaunchApp() {
+ assertDoesNotThrow(() -> App.main(new String[]{}));
+ }
+}
diff --git a/fanout-fanin/src/test/java/com/iluwatar/fanout/fanin/FanOutFanInTest.java b/fanout-fanin/src/test/java/com/iluwatar/fanout/fanin/FanOutFanInTest.java
new file mode 100644
index 000000000..4273d756a
--- /dev/null
+++ b/fanout-fanin/src/test/java/com/iluwatar/fanout/fanin/FanOutFanInTest.java
@@ -0,0 +1,47 @@
+/*
+ * The MIT License
+ * Copyright © 2014-2021 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.fanout.fanin;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+class FanOutFanInTest {
+
+ @Test
+ void fanOutFanInTest() {
+ final List numbers = Arrays.asList(1L, 3L, 4L, 7L, 8L);
+
+ final List requests =
+ numbers.stream().map(SquareNumberRequest::new).collect(Collectors.toList());
+
+ final Consumer consumer = new Consumer(0L);
+
+ final Long sumOfSquaredNumbers = FanOutFanIn.fanOutFanIn(requests, consumer);
+
+ Assertions.assertEquals(139, sumOfSquaredNumbers);
+ }
+}
diff --git a/fanout-fanin/src/test/java/com/iluwatar/fanout/fanin/SquareNumberRequestTest.java b/fanout-fanin/src/test/java/com/iluwatar/fanout/fanin/SquareNumberRequestTest.java
new file mode 100644
index 000000000..86560b38b
--- /dev/null
+++ b/fanout-fanin/src/test/java/com/iluwatar/fanout/fanin/SquareNumberRequestTest.java
@@ -0,0 +1,41 @@
+/*
+ * The MIT License
+ * Copyright © 2014-2021 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.fanout.fanin;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+class SquareNumberRequestTest {
+
+ @Test
+ void delayedSquaringTest() {
+ Consumer consumer = new Consumer(10L);
+
+ SquareNumberRequest squareNumberRequest = new SquareNumberRequest(5L);
+
+ squareNumberRequest.delayedSquaring(consumer);
+
+ Assertions.assertEquals(35, consumer.getSumOfSquaredNumbers().get());
+ }
+}
diff --git a/gpl-3.0.txt b/gpl-3.0.txt
index e72bfddab..6dc84f60c 100644
--- a/gpl-3.0.txt
+++ b/gpl-3.0.txt
@@ -1,3 +1,26 @@
+====
+ The MIT License
+ Copyright © 2014-2021 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.
+====
+
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
diff --git a/lgpl-3.0.txt b/lgpl-3.0.txt
index 0a041280b..d1fcc084e 100644
--- a/lgpl-3.0.txt
+++ b/lgpl-3.0.txt
@@ -1,3 +1,26 @@
+====
+ The MIT License
+ Copyright © 2014-2021 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.
+====
+
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
diff --git a/pom.xml b/pom.xml
index 1ebe0ad23..cfd0de127 100644
--- a/pom.xml
+++ b/pom.xml
@@ -232,6 +232,7 @@
table-module
presentation
lockable-object
+ fanout-fanin
domain-model