Skip to content

Commit 3d474c4

Browse files
committed
resolved checkstyle conflicts
1 parent 3e23c5e commit 3d474c4

File tree

6 files changed

+154
-91
lines changed

6 files changed

+154
-91
lines changed

join/README.md

Lines changed: 100 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -1,119 +1,135 @@
11
---
2-
title: "Join Pattern in Java: Synchronizing Concurrent Tasks"
2+
title: "Join Pattern in Java: Streamlining Concurrent Operations"
33
shortTitle: Join
4-
description: "Learn the Join Design Pattern in Java with detailed examples and explanations. Understand how to synchronize concurrent tasks and manage execution flow using the Join Pattern. Ideal for developers looking to improve their multithreading and synchronization skills."
5-
category: Behavioral
4+
description: "Master the Join Design Pattern in Java to coordinate and synchronize concurrent tasks effectively. Explore examples, code implementations, benefits, and practical applications."
5+
category: Concurrency
66
language: en
7-
issue: #70
87
tag:
98
- Concurrency
109
- Synchronization
11-
- Threads
12-
- Multithreading
13-
- Parallel Execution
10+
- Parallel processing
11+
- Gang of Four
1412
---
1513

16-
## Intent of Join Design Pattern
14+
## Also known as
1715

18-
The **Join Design Pattern** in Java is used to synchronize multiple concurrent processes or threads so that they must all complete before any subsequent tasks can proceed. This pattern is essential when tasks are executed in parallel, but the subsequent tasks need to wait until all parallel tasks are finished. It allows threads to "join" at a synchronization point and ensures correct execution order and timing.
16+
* Fork-Join Pattern
17+
18+
## Intent of Join Pattern
19+
20+
The Join Pattern in Java focuses on coordinating and synchronizing concurrent tasks to achieve a specific outcome. It ensures that multiple tasks can execute independently, and their results are merged once all tasks complete.
1921

2022
## Detailed Explanation of Join Pattern with Real-World Examples
2123

22-
#### Real-World Example
24+
Real-world example
2325

24-
Imagine a **construction project** where multiple contractors are working on different aspects of the building simultaneously. The project manager doesn't want to proceed with the final inspection of the building until all the contractors have finished their respective tasks. Using the **Join Design Pattern**, the manager waits for all contractors (threads) to complete their work before proceeding with the inspection (subsequent task).
26+
> Imagine a multi-chef kitchen preparing different dishes for a single order. Each chef works independently on their assigned dish, but the order cannot be delivered until every dish is ready. The kitchen manager, acting as the join point, ensures synchronization and prepares the final order once all dishes are done. Similarly, the Join Pattern allows tasks to execute concurrently and synchronizes their results for a final outcome.
2527
26-
This pattern allows the project manager to synchronize all contractors' tasks to ensure that the inspection is only performed once all work is completed.
28+
In plain words
2729

28-
#### Wikipedia Definition:
30+
> The Join Pattern helps in synchronizing multiple independent tasks, allowing them to work concurrently and combining their outcomes efficiently.
2931
30-
> "Join is a synchronization technique that allows multiple concurrent threads or processes to synchronize and wait for the completion of other threads before proceeding to subsequent tasks."
32+
Wikipedia says
3133

32-
## Programmatic Example of Join Pattern in Java
34+
> The join design pattern is a parallel processing pattern that helps merge results of concurrently executed tasks.
3335
34-
In this example, we simulate a scenario where four demo tasks run concurrently, and the main thread waits for their completion before proceeding. This is achieved using the **Thread#join()** method, which ensures that the main thread waits for all demo tasks to finish before continuing.
36+
## Programmatic Example of Join Pattern in Java
3537

36-
### DemoThreadClass
38+
In this example, we demonstrate how the Join Pattern can be implemented to manage multiple threads and synchronize their results. We use a task aggregator that collects data from individual tasks and combines it into a final result.
3739

3840
```java
39-
/*
40-
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
41-
*
42-
* The MIT License
43-
* Copyright © 2014-2022 Ilkka Seppälä
44-
*
45-
* Permission is hereby granted, free of charge, to any person obtaining a copy
46-
* of this software and associated documentation files (the "Software"), to deal
47-
* in the Software without restriction, including without limitation the rights
48-
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
49-
* copies of the Software, and to permit persons to whom the Software is
50-
* furnished to do so, subject to the following conditions:
51-
*
52-
* The above copyright notice and this permission notice shall be included in
53-
* all copies or substantial portions of the Software.
54-
*
55-
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
56-
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
57-
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
58-
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
59-
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
60-
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
61-
* THE SOFTWARE.
62-
*/
41+
6342
package com.iluwatar.join;
6443

6544
import lombok.extern.slf4j.Slf4j;
6645

67-
/*
68-
* DemoThreads implementing Runnable
46+
/** Here main thread will execute after completion of 4 demo threads
47+
* main thread will continue when CountDownLatch count becomes 0
48+
* CountDownLatch will start with count 4 and 4 demo threads will decrease it by 1
49+
* everytime when they will finish .
6950
*/
51+
7052
@Slf4j
71-
public class DemoThread implements Runnable {
53+
public class JoinPatternDemo {
54+
55+
/**
56+
* execution of demo and dependent threads.
57+
*/
58+
public static void main(String[] args) {
59+
60+
int[] executionOrder = {4, 2, 1, 3};
61+
int noOfDemoThreads = 4;
62+
int noOfDependentThreads = 2;
63+
JoinPattern pattern = new JoinPattern(noOfDemoThreads, executionOrder);
64+
Thread previous = null;
65+
66+
for (int i = 0; i < noOfDemoThreads; i++) {
67+
previous = new Thread(new DemoThread(executionOrder[i], previous));
68+
previous.start();
69+
}
70+
pattern.await();
7271

73-
private static int[] executionOrder;
74-
private static int[] actualExecutionOrder;
75-
private static int index = 0;
76-
private static JoinPattern pattern;
77-
private int id;
78-
private Thread previous;
72+
//Dependent threads after execution of DemoThreads
73+
for (int i = 0; i < noOfDependentThreads; i++) {
74+
new DependentThread(i + 1).start();
75+
}
76+
LOGGER.info("end of program ");
7977

80-
public DemoThread(int id, Thread previous) {
81-
this.id = id;
82-
this.previous = previous;
78+
}
8379

84-
}
80+
}
8581

86-
public static int[] getActualExecutionOrder() {
87-
return actualExecutionOrder;
88-
}
82+
```
8983

90-
public static void setExecutionOrder(int[] executionOrder, JoinPattern pattern) {
91-
DemoThread.executionOrder = executionOrder;
92-
DemoThread.pattern = pattern;
93-
actualExecutionOrder = new int[executionOrder.length];
94-
}
84+
### Program Output:
9585

96-
public void run() {
97-
if (previous != null) {
98-
try {
99-
previous.join();
100-
} catch (InterruptedException e) {
101-
e.printStackTrace();
102-
}
103-
}
104-
Logger.info("Thread " + id + " starts");
105-
try {
106-
Thread.sleep(id * 250);
107-
108-
} catch (InterruptedException e) {
109-
e.printStackTrace();
110-
} finally {
111-
Logger.info("Thread " + id + " ends");
112-
actualExecutionOrder[index++] = id;
113-
pattern.countdown();
114-
115-
}
116-
}
86+
```
87+
Running com.iluwatar.join.JoinPatternTest
88+
01:13:17.890 [Thread-2] INFO com.iluwatar.join.DemoThread -- Thread 1 starts
89+
01:13:18.167 [Thread-2] INFO com.iluwatar.join.DemoThread -- Thread 1 ends
90+
01:13:18.168 [Thread-3] INFO com.iluwatar.join.DemoThread -- Thread 4 starts
91+
01:13:19.176 [Thread-3] INFO com.iluwatar.join.DemoThread -- Thread 4 ends
92+
01:13:19.176 [Thread-4] INFO com.iluwatar.join.DemoThread -- Thread 3 starts
93+
01:13:19.935 [Thread-4] INFO com.iluwatar.join.DemoThread -- Thread 3 ends
94+
01:13:19.935 [Thread-5] INFO com.iluwatar.join.DemoThread -- Thread 2 starts
95+
01:13:20.437 [Thread-5] INFO com.iluwatar.join.DemoThread -- Thread 2 ends
96+
```
11797

118-
}
98+
## When to Use the Join Pattern in Java
99+
100+
Use the Join Pattern in Java:
101+
102+
* To synchronize results from multiple independent tasks executing in parallel.
103+
* To aggregate and process data from various sources concurrently.
104+
* To reduce the complexity of managing multiple threads in parallel operations.
105+
106+
## Real-World Applications of Join Pattern in Java
107+
108+
* Managing concurrent HTTP requests and aggregating their responses into a single result.
109+
* Parallel processing of large datasets, such as in map-reduce frameworks.
110+
* Synchronizing asynchronous operations, e.g., CompletableFutures in Java.
111+
112+
## Benefits and Trade-offs of Join Pattern
113+
114+
### Benefits:
115+
116+
* Efficiently handles parallel processing tasks with minimal synchronization overhead.
117+
* Improves application performance by utilizing available system resources optimally.
118+
* Simplifies the logic for managing and synchronizing multiple tasks.
119+
120+
### Trade-offs:
121+
122+
* Debugging can become challenging with large numbers of asynchronous tasks.
123+
* Improper use may lead to deadlocks or performance bottlenecks.
124+
125+
## Related Java Design Patterns
126+
127+
* [Fork-Join Framework](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ForkJoinPool.html): Built-in Java framework for recursive task splitting and joining.
128+
* [Future and CompletableFuture](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html): Used for handling and synchronizing asynchronous operations.
129+
* [Observer Pattern](https://java-design-patterns.com/patterns/observer/): Can be combined with Join to monitor task progress.
130+
131+
## References and Credits
119132

133+
* [Java Concurrency in Practice](https://amzn.to/3sfS8mT)
134+
* [Effective Java](https://amzn.to/3GxS8p4)
135+
* [Oracle Java Documentation on Concurrency](https://docs.oracle.com/javase/tutorial/essential/concurrency/)

join/etc/join.urm.puml

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
@startuml
2+
package com.iluwatar.join {
3+
class DemoThread {
4+
- LOGGER : Logger {static}
5+
- actualExecutionOrder : int[] {static}
6+
- executionOrder : int[] {static}
7+
- id : int
8+
- index : int {static}
9+
- pattern : JoinPattern {static}
10+
- previous : Thread
11+
+ DemoThread(id : int, previous : Thread)
12+
+ getActualExecutionOrder() : int[] {static}
13+
+ run()
14+
+ setExecutionOrder(executionOrder : int[], pattern : JoinPattern) {static}
15+
}
16+
class DependentThread {
17+
- LOGGER : Logger {static}
18+
- id : int
19+
~ DependentThread(id : int)
20+
+ run()
21+
}
22+
class JoinPattern {
23+
~ executionOrder : int[]
24+
- latch : CountDownLatch
25+
~ noOfDemoThreads : int
26+
+ JoinPattern(noOfDemoThreads : int, executionOrder : int[])
27+
+ await()
28+
+ countdown()
29+
}
30+
class JoinPatternDemo {
31+
- LOGGER : Logger {static}
32+
+ JoinPatternDemo()
33+
+ main(String[]) {static}
34+
}
35+
}
36+
DemoThread --> "-pattern" JoinPattern
37+
@enduml

join/src/main/java/com/iluwatar/join/DemoThread.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,13 +70,13 @@ public void run() {
7070
e.printStackTrace();
7171
}
7272
}
73-
Logger.info("Thread " + id + " starts");
73+
LOGGER.info("Thread " + id + " starts");
7474
try {
7575
Thread.sleep(id * 250);
7676
} catch (InterruptedException e) {
7777
e.printStackTrace();
7878
} finally {
79-
Logger.info("Thread " + id + " ends");
79+
LOGGER.info("Thread " + id + " ends");
8080
actualExecutionOrder[index++] = id;
8181
pattern.countdown();
8282
}

join/src/main/java/com/iluwatar/join/DependentThread.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
* Dependent threads will execute only after completion of all demothreads.
3333
*/
3434
@Slf4j
35-
public class DependentThread {
35+
public class DependentThread implements Runnable {
3636

3737

3838
private int id;
@@ -44,13 +44,13 @@ public class DependentThread {
4444
*/
4545
public void run() {
4646

47-
Logger.info(" Dependent Thread " + id + " starts ");
47+
LOGGER.info(" Dependent Thread " + id + " starts ");
4848
try {
4949
Thread.sleep(id * 200);
5050
} catch (InterruptedException e) {
5151
e.printStackTrace();
5252
} finally {
53-
Logger.info("Dependent Thread " + id + " completed ");
53+
LOGGER.info("Dependent Thread " + id + " completed ");
5454
}
5555

5656
}

join/src/main/java/com/iluwatar/join/JoinPattern.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,15 +39,25 @@ public class JoinPattern {
3939
private CountDownLatch latch;
4040
int[] executionOrder;
4141

42+
/**
43+
* Initialise join pattern object.
44+
*/
4245
public JoinPattern(int noOfDemoThreads, int[] executionOrder) {
4346
latch = new CountDownLatch(noOfDemoThreads);
4447
this.executionOrder = executionOrder;
48+
DemoThread.setExecutionOrder(executionOrder, this);
4549
}
46-
50+
51+
/**
52+
* decreases count by one.
53+
*/
4754
public void countdown() {
4855
latch.countDown();
4956
}
5057

58+
/**
59+
* thread waits until count reaches 0.
60+
*/
5161
public void await() throws InterruptedException {
5262
latch.await();
5363
}

join/src/main/java/com/iluwatar/join/JoinPatternDemo.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ public static void main(String[] args) {
5656
for (int i = 0; i < noOfDependentThreads; i++) {
5757
new DependentThread(i + 1).start();
5858
}
59-
Logger.info("end of program ");
59+
LOGGER.info("end of program ");
6060

6161
}
6262

0 commit comments

Comments
 (0)