Skip to content

Commit 9f34b25

Browse files
committed
Applied synchronization to prevent CPU usage.
1 parent b29934d commit 9f34b25

File tree

2 files changed

+81
-59
lines changed

2 files changed

+81
-59
lines changed

twin/README.md

+49-38
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ description: "Explore the Twin design pattern in Java with examples. Learn how t
55
category: Structural
66
language: en
77
tag:
8-
- Decoupling
9-
- Object composition
10-
- Performance
11-
- Resilience
8+
- Decoupling
9+
- Object composition
10+
- Performance
11+
- Resilience
1212
---
1313

1414
## Intent of Twin Design Pattern
@@ -21,11 +21,11 @@ Real-world example
2121

2222
> 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).
2323
>
24-
> 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.
24+
> 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.
2525
2626
In plain words
2727

28-
> It provides a way to form two closely coupled subclasses that can act as a twin class having two ends.
28+
> It provides a way to form two closely coupled subclasses that can act as a twin class having two ends.
2929
3030
Wikipedia says
3131

@@ -84,36 +84,47 @@ public class BallItem extends GameItem {
8484
public class BallThread extends Thread {
8585
@Setter
8686
private BallItem twin;
87-
private volatile boolean isSuspended;
8887
private volatile boolean isRunning = true;
88+
private boolean isSuspended = false;
8989

9090
public void run() {
91-
while (isRunning) {
92-
if (!isSuspended) {
91+
synchronized (this) {
92+
while (isRunning) {
93+
while (isSuspended) {
94+
try {
95+
wait();
96+
} catch (InterruptedException e) {
97+
Thread.currentThread().interrupt();
98+
return;
99+
}
100+
}
93101
twin.draw();
94102
twin.move();
95-
}
96-
try {
97-
Thread.sleep(250);
98-
} catch (InterruptedException e) {
99-
throw new RuntimeException(e);
103+
try {
104+
Thread.sleep(250);
105+
} catch (InterruptedException e) {
106+
Thread.currentThread().interrupt();
107+
return;
108+
}
100109
}
101110
}
102111
}
103112

104-
public void suspendMe() {
113+
public synchronized void suspendMe() {
105114
isSuspended = true;
106-
LOGGER.info("Begin to suspend BallThread");
115+
LOGGER.info("Suspending BallThread");
107116
}
108117

109-
public void resumeMe() {
118+
public synchronized void resumeMe() {
110119
isSuspended = false;
111-
LOGGER.info("Begin to resume BallThread");
120+
notify();
121+
LOGGER.info("Resuming BallThread");
112122
}
113123

114-
public void stopMe() {
115-
this.isRunning = false;
116-
this.isSuspended = true;
124+
public synchronized void stopMe() {
125+
isRunning = false;
126+
isSuspended = false;
127+
notify();
117128
}
118129
}
119130
```
@@ -192,40 +203,40 @@ This setup allows `BallItem` and `BallThread` to act together as a single cohesi
192203

193204
## When to Use the Twin Pattern in Java
194205

195-
* 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.
196-
* Useful in performance-critical applications where inheritance might introduce unnecessary overhead.
197-
* Applicable in systems requiring resilience through the ability to replace or update one of the twins without affecting the other.
206+
- 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.
207+
- Useful in performance-critical applications where inheritance might introduce unnecessary overhead.
208+
- Applicable in systems requiring resilience through the ability to replace or update one of the twins without affecting the other.
198209

199210
## Twin Pattern Java Tutorials
200211

201-
* [Twin – A Design Pattern for Modeling Multiple Inheritance (Hanspeter Mössenböck)](http://www.ssw.uni-linz.ac.at/Research/Papers/Moe99/Paper.pdf)
212+
- [Twin – A Design Pattern for Modeling Multiple Inheritance (Hanspeter Mössenböck)](http://www.ssw.uni-linz.ac.at/Research/Papers/Moe99/Paper.pdf)
202213

203214
## Real-World Applications of Twin Pattern in Java
204215

205-
* User interfaces where different frameworks are used for rendering and logic.
206-
* Systems integrating legacy code with new implementations where direct inheritance is not feasible.
216+
- User interfaces where different frameworks are used for rendering and logic.
217+
- Systems integrating legacy code with new implementations where direct inheritance is not feasible.
207218

208219
## Benefits and Trade-offs of Twin Pattern
209220

210221
Benefits:
211222

212-
* Reduces coupling between classes, promoting modularity and easier maintenance.
213-
* Improves flexibility and reuse of classes across different frameworks or languages.
214-
* Enhances performance by avoiding the overhead associated with inheritance.
223+
- Reduces coupling between classes, promoting modularity and easier maintenance.
224+
- Improves flexibility and reuse of classes across different frameworks or languages.
225+
- Enhances performance by avoiding the overhead associated with inheritance.
215226

216227
Trade-offs:
217228

218-
* Can lead to code duplication if not managed properly.
219-
* Increased complexity in managing the interaction between twin classes.
229+
- Can lead to code duplication if not managed properly.
230+
- Increased complexity in managing the interaction between twin classes.
220231

221232
## Related Java Design Patterns
222233

223-
* [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.
224-
* [Bridge](https://java-design-patterns.com/patterns/bridge/): Similar in decoupling abstraction from implementation, but Twin specifically avoids inheritance.
225-
* [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.
234+
- [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.
235+
- [Bridge](https://java-design-patterns.com/patterns/bridge/): Similar in decoupling abstraction from implementation, but Twin specifically avoids inheritance.
236+
- [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.
226237

227238
## References and Credits
228239

229-
* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)
230-
* [Java Design Patterns: A Hands-On Experience with Real-World Examples](https://amzn.to/3yhh525)
231-
* [Patterns of Enterprise Application Architecture](https://amzn.to/3WfKBPR)
240+
- [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)
241+
- [Java Design Patterns: A Hands-On Experience with Real-World Examples](https://amzn.to/3yhh525)
242+
- [Patterns of Enterprise Application Architecture](https://amzn.to/3WfKBPR)

twin/src/main/java/com/iluwatar/twin/BallThread.java

+32-21
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/*
2-
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
2+
* This project is licensed under the MIT license. Module model-view-viewmodel
3+
* is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
34
*
45
* The MIT License
56
* Copyright © 2014-2022 Ilkka Seppälä
@@ -28,8 +29,10 @@
2829
import lombok.extern.slf4j.Slf4j;
2930

3031
/**
31-
* This class is a UI thread for drawing the {@link BallItem}, and provide the method for suspend
32-
* and resume. It holds the reference of {@link BallItem} to delegate the draw task.
32+
* This class is a UI thread for drawing the {@link BallItem}, and provides
33+
* methods to suspend
34+
* and resume execution. It holds the reference of {@link BallItem} to delegate
35+
* the draw task.
3336
*/
3437

3538
@Slf4j
@@ -38,41 +41,49 @@ public class BallThread extends Thread {
3841
@Setter
3942
private BallItem twin;
4043

41-
private volatile boolean isSuspended;
42-
4344
private volatile boolean isRunning = true;
45+
private boolean isSuspended = false; // Removed volatile, now synchronized.
4446

4547
/**
4648
* Run the thread.
4749
*/
4850
public void run() {
49-
50-
while (isRunning) {
51-
if (!isSuspended) {
51+
synchronized (this) {
52+
while (isRunning) {
53+
while (isSuspended) {
54+
try {
55+
wait(); // Puts the thread in waiting state.
56+
} catch (InterruptedException e) {
57+
Thread.currentThread().interrupt(); // Restores the interruption.
58+
return;
59+
}
60+
}
5261
twin.draw();
5362
twin.move();
54-
}
55-
try {
56-
Thread.sleep(250);
57-
} catch (InterruptedException e) {
58-
throw new RuntimeException(e);
63+
try {
64+
Thread.sleep(250);
65+
} catch (InterruptedException e) {
66+
Thread.currentThread().interrupt();
67+
return;
68+
}
5969
}
6070
}
6171
}
6272

63-
public void suspendMe() {
73+
public synchronized void suspendMe() {
6474
isSuspended = true;
65-
LOGGER.info("Begin to suspend BallThread");
75+
LOGGER.info("Suspending BallThread");
6676
}
6777

68-
public void resumeMe() {
78+
public synchronized void resumeMe() {
6979
isSuspended = false;
70-
LOGGER.info("Begin to resume BallThread");
80+
notify(); // Wakes up the thread from waiting state.
81+
LOGGER.info("Resuming BallThread");
7182
}
7283

73-
public void stopMe() {
74-
this.isRunning = false;
75-
this.isSuspended = true;
84+
public synchronized void stopMe() {
85+
isRunning = false;
86+
isSuspended = false;
87+
notify(); // Makes sure the thread wakes up and exits (stops).
7688
}
7789
}
78-

0 commit comments

Comments
 (0)