From b29934d2344332ffc9de0b0641099161311b0109 Mon Sep 17 00:00:00 2001 From: Francisco G P Date: Mon, 10 Mar 2025 12:49:30 -0700 Subject: [PATCH 1/4] Added and translated map-reduce README.md to Spanish. --- localization/es/map-reduce/README.md | 256 +++++++++++++++++++++++++++ 1 file changed, 256 insertions(+) create mode 100644 localization/es/map-reduce/README.md diff --git a/localization/es/map-reduce/README.md b/localization/es/map-reduce/README.md new file mode 100644 index 000000000000..28a77f0062a1 --- /dev/null +++ b/localization/es/map-reduce/README.md @@ -0,0 +1,256 @@ +--- +title: "Patrón de Diseño MapReduce en Java" +shortTitle: MapReduce +description: "Aprende el patrón de diseño MapReduce en Java con ejemplos de la vida real, diagramas de clases y tutoriales. Entiende su intención, aplicación, beneficios y usos conocidos para mejorar tu conocimiento sobre patrones de diseño." +category: Optimización de Rendimiento +language: es +tag: + - Data processing + - Code simplification + - Delegation + - Performance + - Procesamiento de datos + - Simplificación de coódigo + - Delegación + - Rendimiento +--- + +## También conocido como: + +- Estrategia Separa-Aplica-Combina (Split-Apply-Combine Strategy) +- Patrón Dispersa-Recolecta (Scatter-Gather Pattern) + +## Intención del Patrón de Diseño Map Reduce + +MapReduce pretende procesar y generar grandes conjuntos de datos con un algoritmo en paralelo y distribuido en un grupo. Divide la carga de trabajo en dos fases principales: Mapear (Map) y Reducir (Reduce), permitiendo así una mayor eficiencia en procesamiento de datos en paralelo. + +## Explicación Detallada del Patrón de Diseño Map Reduce con Ejemplos del Mundo Real + +Ejemplo Práctico + +> Imagina una compañía de comercio en línea (e-commerce) que quiere analizar sus datos de ventas a lo largo de múltplies regiones. Tienen terabytes de datos de transacciones almacenados en cientos de servidores. Usando MapReduce, pueden procesar estos datos eficientemente para calcular las ventas totales por categoría de producto. La función Map procesaría registros de ventas individuales, regresando pares clave-valor de (categoría, cantidad de venta). La función Reduce entonces sumaría todas las cantidades de ventas por cada categoría, produciendo el resultado final. + +En palabras sencillas + +> MapReduce divide un gran problema en partes más pequeñas, las procesa en paralelo y después combina los resultados. + +En Wikipedia dice: + +> "MapReduce es un modelo de programación e implementación asociada para procesar y generar grandes conjuntos de información con un algoritmo en paralelo y distribuido en un grupo". +> MapReduce consiste de dos funciones principales: +> El nodo principal toma la entrada de información, la divide en problemas más pequeños (sub-problemas) y los distribuye a los nodos restantes (de trabajo). Un nodo de trabajo puede repetir este proceso llevando a una estructura de árbol multinivel. El nodo de trabajo procesa el sub-problema y le regresa la respuesta al nodo principal. +> El nodo principal recolecta todas las respuestas de todos los sub-problemas y las combina de cierta manera para regresar la salida de información - la respuesta del principal problema que estaba resolviendo. +> Este acercamiento permite un procesamiento eficiente de grandes cantidades de datos através de múltiples máquinas, convirtiéndola en una técnica fundamental en análisis de cantidades enormes de datos y computo distribuido. + +## Ejemplo Programático de Map Reduce en Java + +### 1. Fase de Map (Mapeador; División & Procesamiento de Datos) + +- El Mapper toma una entrada de texto (string), lo divide en palabras y cuenta las ocurrencias. +- Salida: Un mapa {palabra → conteo} por cada línea de entrada. + +#### `Mapper.java` + +```java +public class Mapper { + public static Map map(String input) { + Map wordCount = new HashMap<>(); + String[] words = input.split("\\s+"); + for (String word : words) { + word = word.toLowerCase().replaceAll("[^a-z]", ""); + if (!word.isEmpty()) { + wordCount.put(word, wordCount.getOrDefault(word, 0) + 1); + } + } + return wordCount; + } +} +``` + +Ejemplo de Entrada: `"Hello world hello"` +Salida: `{hello=2, world=1}` + +### 2. Fase de Shuffle (Combinación; Agrupar Datos por Clave) + +- La Combinación recolecta pares clave-valor de múltiples mapeadores (mappers) y valores de grupo por clave. + +#### `Shuffler.java` + +```java +public class Shuffler { + public static Map> shuffleAndSort(List> mapped) { + Map> grouped = new HashMap<>(); + for (Map map : mapped) { + for (Map.Entry entry : map.entrySet()) { + grouped.putIfAbsent(entry.getKey(), new ArrayList<>()); + grouped.get(entry.getKey()).add(entry.getValue()); + } + } + return grouped; + } +} +``` + +Ejemplo de Entrada: + +``` +[ + {"hello": 2, "world": 1}, + {"hello": 1, "java": 1} +] +``` + +Salida: + +``` +{ + "hello": [2, 1], + "world": [1], + "java": [1] +} +``` + +### 3. Fase de Reduce (Reductor; Agregar Resultados) + +- El Reductor suma todas las ocurrencias de cada palabra. + +#### `Reducer.java` + +```java +public class Reducer { + public static List> reduce(Map> grouped) { + Map reduced = new HashMap<>(); + for (Map.Entry> entry : grouped.entrySet()) { + reduced.put(entry.getKey(), entry.getValue().stream().mapToInt(Integer::intValue).sum()); + } + + List> result = new ArrayList<>(reduced.entrySet()); + result.sort(Map.Entry.comparingByValue(Comparator.reverseOrder())); + return result; + } +} +``` + +Ejemplo de Entrada: + +``` +{ + "hello": [2, 1], + "world": [1], + "java": [1] +} +``` + +Salida: + +``` +[ + {"hello": 3}, + {"world": 1}, + {"java": 1} +] +``` + +### 4. Ejecutar el Proceso Completo de MapReduce + +- La clase MapReduce coordina los tres pasos. + +#### `MapReduce.java` + +```java +public class MapReduce { + public static List> mapReduce(List inputs) { + List> mapped = new ArrayList<>(); + for (String input : inputs) { + mapped.add(Mapper.map(input)); + } + + Map> grouped = Shuffler.shuffleAndSort(mapped); + + return Reducer.reduce(grouped); + } +} +``` + +### 5. Ejecución Principal (Llamar a MapReduce) + +- La clase Main ejecuta el "pipeline" de MapReduce y regresa el conteo final de palabras. + +#### `Main.java` + +```java + public static void main(String[] args) { + List inputs = Arrays.asList( + "Hello world hello", + "MapReduce is fun", + "Hello from the other side", + "Hello world" + ); + List> result = MapReduce.mapReduce(inputs); + for (Map.Entry entry : result) { + System.out.println(entry.getKey() + ": " + entry.getValue()); + } +} +``` + +Salida: + +``` +hello: 4 +world: 2 +the: 1 +other: 1 +side: 1 +mapreduce: 1 +is: 1 +from: 1 +fun: 1 +``` + +## Cuándo Usar el Patrón de Diseño MapReduce en Java + +Usa MapReduce cuando se están: + +- Procesando grandes conjuntos de información que no quepa en la memoria de una sola máquina. +- Realizando cálculos que se puedan desarrollar en paralelo. +- Trabajando en escenarios tolerante a fallos y computación distribuida. +- Analizando archivos de registro, datos de rastreo web o datos científicos. + +## Tutoriales del Patrón de Diseño MapReduce en Java + +- [Tutorial MapReduce (Apache Hadoop)](https://hadoop.apache.org/docs/stable/hadoop-mapreduce-client/hadoop-mapreduce-client-core/MapReduceTutorial.html) +- [Ejemplo MapReduce (Simplilearn)](https://www.youtube.com/watch?v=l2clwKnrtO8) + +## Ventajas y Desventajas del Patrón de Diseño MapReduce + +Ventajas: + +- Escalabilidad: Puede procesar grandes cantidades de datos através de múltiples máquinas +- Tolerancia a Fallos: Maneja los fallos elegantemente +- Simplicidad: Resume detalles complejos de distribución computacional + +Desventajas: + +- Costo-Beneficio: Ineficiente para conjuntos de datos chicos por la preparación y coordinación necesaria +- Flexibilidad Limitada: Inadecuado para todos los tipos de computación o algoritmos +- Latencia: En relación a lotes de información podría ser inadecaudo para necesidades de procesamiento en tiempo real + +## Aplicaciones Reales para el Patrón de Diseño MapReduce en Java + +- Implementación original de Google para indexar páginas web +- Hadoop MapReduce para procesamiento de información extensa +- Sistemas de análisis de registros a gran escala +- Secuencia genómica en análisis de bio-informática + +## Patrones de Diseño relacionados a Java + +- Patrón de Encadenamiento (Chaining Pattern) +- Patrón de Maestro-Trabajador (Master-Worker Pattern) +- Patrón de Tubería (Pipeline Pattern) + +## Referencias y Creditos + +- [¿Qué es MapReduce?](https://www.ibm.com/think/topics/mapreduce) +- [¿Por qué MapReduce no ha muerto?](https://www.codemotion.com/magazine/ai-ml/big-data/mapreduce-not-dead-heres-why-its-still-ruling-in-the-cloud/) +- [Soluciones Escalables de Procesamiento de Datos Distribuidos](https://tcpp.cs.gsu.edu/curriculum/?q=system%2Ffiles%2Fch07.pdf) +- [Patrones de Diseño en Java: Experiencia Práctica con Ejemplos del Mundo Real](https://amzn.to/3HWNf4U) From 9f34b251a7812032d3729173c4b7d71bce609e21 Mon Sep 17 00:00:00 2001 From: Francisco G P Date: Tue, 18 Mar 2025 14:04:45 -0700 Subject: [PATCH 2/4] Applied synchronization to prevent CPU usage. --- twin/README.md | 87 +++++++++++-------- .../java/com/iluwatar/twin/BallThread.java | 53 ++++++----- 2 files changed, 81 insertions(+), 59 deletions(-) diff --git a/twin/README.md b/twin/README.md index b2913e0a963f..b1cb39f86940 100644 --- a/twin/README.md +++ b/twin/README.md @@ -5,10 +5,10 @@ description: "Explore the Twin design pattern in Java with examples. Learn how t category: Structural language: en tag: - - Decoupling - - Object composition - - Performance - - Resilience + - Decoupling + - Object composition + - Performance + - Resilience --- ## Intent of Twin Design Pattern @@ -21,11 +21,11 @@ Real-world example > An analogous real-world example of the Twin design pattern can be found in the relationship between a driver and a driving simulator. Imagine a driver (the first class) and a driving simulator (the second class) that both need to interact with the same set of vehicle controls (steering, acceleration, braking) and receive the same feedback (speed, engine status). > -> Despite performing similar functions, the driver and the simulator cannot share a common base class because they operate in fundamentally different environments—one in the physical world and the other in a virtual environment. Instead, they are "twinned" to ensure consistent interaction with the vehicle controls and feedback mechanisms. This setup allows improvements or changes to be made to the simulator without affecting the driver and vice versa, maintaining the system's overall flexibility and resilience. +> Despite performing similar functions, the driver and the simulator cannot share a common base class because they operate in fundamentally different environments—one in the physical world and the other in a virtual environment. Instead, they are "twinned" to ensure consistent interaction with the vehicle controls and feedback mechanisms. This setup allows improvements or changes to be made to the simulator without affecting the driver and vice versa, maintaining the system's overall flexibility and resilience. In plain words -> It provides a way to form two closely coupled subclasses that can act as a twin class having two ends. +> It provides a way to form two closely coupled subclasses that can act as a twin class having two ends. Wikipedia says @@ -84,36 +84,47 @@ public class BallItem extends GameItem { public class BallThread extends Thread { @Setter private BallItem twin; - private volatile boolean isSuspended; private volatile boolean isRunning = true; + private boolean isSuspended = false; public void run() { - while (isRunning) { - if (!isSuspended) { + synchronized (this) { + while (isRunning) { + while (isSuspended) { + try { + wait(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + return; + } + } twin.draw(); twin.move(); - } - try { - Thread.sleep(250); - } catch (InterruptedException e) { - throw new RuntimeException(e); + try { + Thread.sleep(250); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + return; + } } } } - public void suspendMe() { + public synchronized void suspendMe() { isSuspended = true; - LOGGER.info("Begin to suspend BallThread"); + LOGGER.info("Suspending BallThread"); } - public void resumeMe() { + public synchronized void resumeMe() { isSuspended = false; - LOGGER.info("Begin to resume BallThread"); + notify(); + LOGGER.info("Resuming BallThread"); } - public void stopMe() { - this.isRunning = false; - this.isSuspended = true; + public synchronized void stopMe() { + isRunning = false; + isSuspended = false; + notify(); } } ``` @@ -192,40 +203,40 @@ This setup allows `BallItem` and `BallThread` to act together as a single cohesi ## When to Use the Twin Pattern in Java -* Use when you need to decouple classes that share common functionality but cannot inherit from a common base class due to various reasons such as the use of different frameworks or languages. -* Useful in performance-critical applications where inheritance might introduce unnecessary overhead. -* Applicable in systems requiring resilience through the ability to replace or update one of the twins without affecting the other. +- Use when you need to decouple classes that share common functionality but cannot inherit from a common base class due to various reasons such as the use of different frameworks or languages. +- Useful in performance-critical applications where inheritance might introduce unnecessary overhead. +- Applicable in systems requiring resilience through the ability to replace or update one of the twins without affecting the other. ## Twin Pattern Java Tutorials -* [Twin – A Design Pattern for Modeling Multiple Inheritance (Hanspeter Mössenböck)](http://www.ssw.uni-linz.ac.at/Research/Papers/Moe99/Paper.pdf) +- [Twin – A Design Pattern for Modeling Multiple Inheritance (Hanspeter Mössenböck)](http://www.ssw.uni-linz.ac.at/Research/Papers/Moe99/Paper.pdf) ## Real-World Applications of Twin Pattern in Java -* User interfaces where different frameworks are used for rendering and logic. -* Systems integrating legacy code with new implementations where direct inheritance is not feasible. +- User interfaces where different frameworks are used for rendering and logic. +- Systems integrating legacy code with new implementations where direct inheritance is not feasible. ## Benefits and Trade-offs of Twin Pattern Benefits: -* Reduces coupling between classes, promoting modularity and easier maintenance. -* Improves flexibility and reuse of classes across different frameworks or languages. -* Enhances performance by avoiding the overhead associated with inheritance. +- Reduces coupling between classes, promoting modularity and easier maintenance. +- Improves flexibility and reuse of classes across different frameworks or languages. +- Enhances performance by avoiding the overhead associated with inheritance. Trade-offs: -* Can lead to code duplication if not managed properly. -* Increased complexity in managing the interaction between twin classes. +- Can lead to code duplication if not managed properly. +- Increased complexity in managing the interaction between twin classes. ## Related Java Design Patterns -* [Adapter](https://java-design-patterns.com/patterns/adapter/): Both patterns deal with compatibility issues, but Adapter focuses on converting interfaces while Twin deals with class collaboration without inheritance. -* [Bridge](https://java-design-patterns.com/patterns/bridge/): Similar in decoupling abstraction from implementation, but Twin specifically avoids inheritance. -* [Proxy](https://java-design-patterns.com/patterns/proxy/): Manages object access, similar to how Twin handles interaction, but Proxy typically focuses on control and logging. +- [Adapter](https://java-design-patterns.com/patterns/adapter/): Both patterns deal with compatibility issues, but Adapter focuses on converting interfaces while Twin deals with class collaboration without inheritance. +- [Bridge](https://java-design-patterns.com/patterns/bridge/): Similar in decoupling abstraction from implementation, but Twin specifically avoids inheritance. +- [Proxy](https://java-design-patterns.com/patterns/proxy/): Manages object access, similar to how Twin handles interaction, but Proxy typically focuses on control and logging. ## References and Credits -* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI) -* [Java Design Patterns: A Hands-On Experience with Real-World Examples](https://amzn.to/3yhh525) -* [Patterns of Enterprise Application Architecture](https://amzn.to/3WfKBPR) +- [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI) +- [Java Design Patterns: A Hands-On Experience with Real-World Examples](https://amzn.to/3yhh525) +- [Patterns of Enterprise Application Architecture](https://amzn.to/3WfKBPR) diff --git a/twin/src/main/java/com/iluwatar/twin/BallThread.java b/twin/src/main/java/com/iluwatar/twin/BallThread.java index 9d4d9cf71a76..c3d71b34e33f 100644 --- a/twin/src/main/java/com/iluwatar/twin/BallThread.java +++ b/twin/src/main/java/com/iluwatar/twin/BallThread.java @@ -1,5 +1,6 @@ /* - * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * 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ä @@ -28,8 +29,10 @@ import lombok.extern.slf4j.Slf4j; /** - * This class is a UI thread for drawing the {@link BallItem}, and provide the method for suspend - * and resume. It holds the reference of {@link BallItem} to delegate the draw task. + * This class is a UI thread for drawing the {@link BallItem}, and provides + * methods to suspend + * and resume execution. It holds the reference of {@link BallItem} to delegate + * the draw task. */ @Slf4j @@ -38,41 +41,49 @@ public class BallThread extends Thread { @Setter private BallItem twin; - private volatile boolean isSuspended; - private volatile boolean isRunning = true; + private boolean isSuspended = false; // Removed volatile, now synchronized. /** * Run the thread. */ public void run() { - - while (isRunning) { - if (!isSuspended) { + synchronized (this) { + while (isRunning) { + while (isSuspended) { + try { + wait(); // Puts the thread in waiting state. + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); // Restores the interruption. + return; + } + } twin.draw(); twin.move(); - } - try { - Thread.sleep(250); - } catch (InterruptedException e) { - throw new RuntimeException(e); + try { + Thread.sleep(250); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + return; + } } } } - public void suspendMe() { + public synchronized void suspendMe() { isSuspended = true; - LOGGER.info("Begin to suspend BallThread"); + LOGGER.info("Suspending BallThread"); } - public void resumeMe() { + public synchronized void resumeMe() { isSuspended = false; - LOGGER.info("Begin to resume BallThread"); + notify(); // Wakes up the thread from waiting state. + LOGGER.info("Resuming BallThread"); } - public void stopMe() { - this.isRunning = false; - this.isSuspended = true; + public synchronized void stopMe() { + isRunning = false; + isSuspended = false; + notify(); // Makes sure the thread wakes up and exits (stops). } } - From dd45cb08233143a7d7b52cdf770a2c1f31e8f4f9 Mon Sep 17 00:00:00 2001 From: Francisco G P Date: Tue, 18 Mar 2025 14:49:23 -0700 Subject: [PATCH 3/4] Synchronization updated thanks to GitHub Actions. --- twin/README.md | 4 ++-- twin/src/main/java/com/iluwatar/twin/BallThread.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/twin/README.md b/twin/README.md index b1cb39f86940..daa264c5a783 100644 --- a/twin/README.md +++ b/twin/README.md @@ -117,14 +117,14 @@ public class BallThread extends Thread { public synchronized void resumeMe() { isSuspended = false; - notify(); + notifyAll(); LOGGER.info("Resuming BallThread"); } public synchronized void stopMe() { isRunning = false; isSuspended = false; - notify(); + notifyAll(); } } ``` diff --git a/twin/src/main/java/com/iluwatar/twin/BallThread.java b/twin/src/main/java/com/iluwatar/twin/BallThread.java index c3d71b34e33f..a10dcd57e875 100644 --- a/twin/src/main/java/com/iluwatar/twin/BallThread.java +++ b/twin/src/main/java/com/iluwatar/twin/BallThread.java @@ -77,13 +77,13 @@ public synchronized void suspendMe() { public synchronized void resumeMe() { isSuspended = false; - notify(); // Wakes up the thread from waiting state. + notifyAll(); // Wakes up the thread from waiting state (prevents lost wake-ups). LOGGER.info("Resuming BallThread"); } public synchronized void stopMe() { isRunning = false; isSuspended = false; - notify(); // Makes sure the thread wakes up and exits (stops). + notifyAll(); // Makes sure the thread wakes up and exits (prevents lost wake-ups). } } From 0d2cdb195f7fb5400808e826f7908c2ca461e352 Mon Sep 17 00:00:00 2001 From: Francisco G P Date: Tue, 18 Mar 2025 15:01:39 -0700 Subject: [PATCH 4/4] Updated to GitHub Actions comments. --- twin/README.md | 5 ++++- twin/src/main/java/com/iluwatar/twin/BallThread.java | 6 +++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/twin/README.md b/twin/README.md index daa264c5a783..05199911b796 100644 --- a/twin/README.md +++ b/twin/README.md @@ -90,7 +90,7 @@ public class BallThread extends Thread { public void run() { synchronized (this) { while (isRunning) { - while (isSuspended) { + while (isSuspended && isRunning) { try { wait(); } catch (InterruptedException e) { @@ -98,6 +98,9 @@ public class BallThread extends Thread { return; } } + + if (!isRunning) break; + twin.draw(); twin.move(); try { diff --git a/twin/src/main/java/com/iluwatar/twin/BallThread.java b/twin/src/main/java/com/iluwatar/twin/BallThread.java index a10dcd57e875..4a6911320d03 100644 --- a/twin/src/main/java/com/iluwatar/twin/BallThread.java +++ b/twin/src/main/java/com/iluwatar/twin/BallThread.java @@ -50,7 +50,7 @@ public class BallThread extends Thread { public void run() { synchronized (this) { while (isRunning) { - while (isSuspended) { + while (isSuspended && isRunning) { try { wait(); // Puts the thread in waiting state. } catch (InterruptedException e) { @@ -58,6 +58,10 @@ public void run() { return; } } + + if (!isRunning) + break; // Secures clean exit + twin.draw(); twin.move(); try {