Skip to content

Commit 0dd466c

Browse files
committed
docs: update priority queue
1 parent 9665381 commit 0dd466c

File tree

1 file changed

+119
-102
lines changed

1 file changed

+119
-102
lines changed

priority-queue/README.md

Lines changed: 119 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -1,168 +1,160 @@
11
---
2-
title: Priority Queue Pattern
3-
category: Behavioral
2+
title: Priority Queue
3+
category: Concurrency
44
language: en
55
tag:
6-
- Decoupling
7-
- Cloud distributed
6+
- Performance
7+
- Scalability
8+
- Synchronization
9+
- Thread management
810
---
911

12+
## Also known as
13+
14+
* Priority Heap
15+
* Priority List
16+
1017
## Intent
1118

12-
Prioritize requests sent to services so that requests with a higher priority are received and
13-
processed more quickly than those of a lower priority. This pattern is useful in applications that
14-
offer different service level guarantees to individual clients.
19+
The Priority Queue design pattern provides a way to manage a collection of elements where each element has a priority, and elements are accessed and removed based on their priority rather than their insertion order.
1520

1621
## Explanation
1722

18-
Applications may delegate specific tasks to other services; for example, to perform background
19-
processing or to integrate with other applications or services. In the cloud, a message queue is
20-
typically used to delegate tasks to background processing. In many cases the order in which requests
21-
are received by a service is not important. However, in some cases it may be necessary to prioritize
22-
specific requests. These requests should be processed earlier than others of a lower priority that
23-
may have been sent previously by the application.
24-
2523
Real world example
2624

27-
> Imagine a video processing service with free and premium customers. The requests coming from the
28-
> paying premium customers should be prioritized over the others.
25+
> Imagine an emergency room in a hospital. Patients arrive with varying degrees of urgency: some have minor injuries, while others have life-threatening conditions. The hospital uses a priority queue system to manage these patients. Instead of treating patients on a first-come, first-served basis, the medical staff assigns a priority level to each patient based on the severity of their condition. Patients with more critical conditions (higher priority) are treated before those with less severe issues, ensuring that urgent cases receive immediate attention. This system efficiently manages resources and prioritizes care, similar to how a priority queue handles elements based on their priority.
2926
3027
In plain words
3128

32-
> Priority Queue enables processing of high priority messages first, regardless of queue size or
33-
> message age.
29+
> Priority Queue enables processing of high priority messages first, regardless of queue size or message age.
3430
3531
Wikipedia says
3632

37-
> In computer science, a priority queue is an abstract data type similar to regular queue or stack
38-
> data structure in which each element additionally has a "priority" associated with it. In a
39-
> priority queue, an element with high priority is served before an element with low priority.
33+
> In computer science, a priority queue is an abstract data type similar to regular queue or stack data structure in which each element additionally has a "priority" associated with it. In a priority queue, an element with high priority is served before an element with low priority.
4034
4135
**Programmatic Example**
4236

43-
Looking at the video processing example from above, let's first see the `Message` structure.
37+
Looking at a video processing example, let's first see the `Message` structure.
4438

4539
```java
4640
public class Message implements Comparable<Message> {
4741

48-
private final String message;
49-
private final int priority; // define message priority in queue
42+
private final String message;
43+
private final int priority; // define message priority in queue
5044

51-
public Message(String message, int priority) {
52-
this.message = message;
53-
this.priority = priority;
54-
}
45+
public Message(String message, int priority) {
46+
this.message = message;
47+
this.priority = priority;
48+
}
5549

56-
@Override
57-
public int compareTo(Message o) {
58-
return priority - o.priority;
59-
}
60-
...
50+
@Override
51+
public int compareTo(Message o) {
52+
return priority - o.priority;
53+
}
54+
// ...
6155
}
6256
```
6357

64-
Here's `PriorityMessageQueue` that handles storing the messages and serving them in priority
65-
order.
58+
Here's `PriorityMessageQueue` that handles storing the messages and serving them in priority order.
6659

6760
```java
6861
public class PriorityMessageQueue<T extends Comparable> {
6962

70-
...
63+
// ...
64+
65+
public T remove() {
66+
if (isEmpty()) {
67+
return null;
68+
}
69+
70+
final var root = queue[0];
71+
queue[0] = queue[size - 1];
72+
size--;
73+
maxHeapifyDown();
74+
return root;
75+
}
7176

72-
public T remove() {
73-
if (isEmpty()) {
74-
return null;
77+
public void add(T t) {
78+
ensureCapacity();
79+
queue[size] = t;
80+
size++;
81+
maxHeapifyUp();
7582
}
7683

77-
final var root = queue[0];
78-
queue[0] = queue[size - 1];
79-
size--;
80-
maxHeapifyDown();
81-
return root;
82-
}
83-
84-
public void add(T t) {
85-
ensureCapacity();
86-
queue[size] = t;
87-
size++;
88-
maxHeapifyUp();
89-
}
90-
91-
...
84+
// ...
9285
}
9386
```
9487

95-
`QueueManager` has a `PriorityMessageQueue` and makes it easy to `publishMessage` and
96-
`receiveMessage`.
88+
`QueueManager` has a `PriorityMessageQueue` and makes it easy to `publishMessage` and `receiveMessage`.
9789

9890
```java
9991
public class QueueManager {
10092

101-
private final PriorityMessageQueue<Message> messagePriorityMessageQueue;
93+
private final PriorityMessageQueue<Message> messagePriorityMessageQueue;
10294

103-
public QueueManager(int initialCapacity) {
104-
messagePriorityMessageQueue = new PriorityMessageQueue<>(new Message[initialCapacity]);
105-
}
95+
public QueueManager(int initialCapacity) {
96+
messagePriorityMessageQueue = new PriorityMessageQueue<>(new Message[initialCapacity]);
97+
}
10698

107-
public void publishMessage(Message message) {
108-
messagePriorityMessageQueue.add(message);
109-
}
99+
public void publishMessage(Message message) {
100+
messagePriorityMessageQueue.add(message);
101+
}
110102

111-
public Message receiveMessage() {
112-
if (messagePriorityMessageQueue.isEmpty()) {
113-
return null;
103+
public Message receiveMessage() {
104+
if (messagePriorityMessageQueue.isEmpty()) {
105+
return null;
106+
}
107+
return messagePriorityMessageQueue.remove();
114108
}
115-
return messagePriorityMessageQueue.remove();
116-
}
117109
}
118110
```
119111

120112
`Worker` constantly polls `QueueManager` for highest priority message and processes it.
121113

122114
```java
115+
123116
@Slf4j
124117
public class Worker {
125118

126-
private final QueueManager queueManager;
127-
128-
public Worker(QueueManager queueManager) {
129-
this.queueManager = queueManager;
130-
}
131-
132-
public void run() throws Exception {
133-
while (true) {
134-
var message = queueManager.receiveMessage();
135-
if (message == null) {
136-
LOGGER.info("No Message ... waiting");
137-
Thread.sleep(200);
138-
} else {
139-
processMessage(message);
140-
}
119+
private final QueueManager queueManager;
120+
121+
public Worker(QueueManager queueManager) {
122+
this.queueManager = queueManager;
141123
}
142-
}
143124

144-
private void processMessage(Message message) {
145-
LOGGER.info(message.toString());
146-
}
125+
public void run() throws Exception {
126+
while (true) {
127+
var message = queueManager.receiveMessage();
128+
if (message == null) {
129+
LOGGER.info("No Message ... waiting");
130+
Thread.sleep(200);
131+
} else {
132+
processMessage(message);
133+
}
134+
}
135+
}
136+
137+
private void processMessage(Message message) {
138+
LOGGER.info(message.toString());
139+
}
147140
}
148141
```
149142

150-
Here's the full example how we create an instance of `QueueManager` and process messages using
151-
`Worker`.
143+
Here's the full example how we create an instance of `QueueManager` and process messages using `Worker`.
152144

153145
```java
154-
var queueManager = new QueueManager(100);
146+
var queueManager = new QueueManager(100);
155147

156-
for (var i = 0; i < 100; i++) {
157-
queueManager.publishMessage(new Message("Low Message Priority", 0));
158-
}
148+
for (var i = 0; i< 100; i++) {
149+
queueManager.publishMessage(new Message("Low Message Priority", 0));
150+
}
159151

160-
for (var i = 0; i < 100; i++) {
161-
queueManager.publishMessage(new Message("High Message Priority", 1));
162-
}
152+
for(var i = 0; i< 100; i++) {
153+
queueManager.publishMessage(new Message("High Message Priority", 1));
154+
}
163155

164-
var worker = new Worker(queueManager);
165-
worker.run();
156+
var worker = new Worker(queueManager);
157+
worker.run();
166158
```
167159

168160
Program output:
@@ -193,7 +185,6 @@ No Message ... waiting
193185
No Message ... waiting
194186
```
195187

196-
197188
## Class diagram
198189

199190
![alt text](./etc/priority-queue.urm.png "Priority Queue pattern class diagram")
@@ -202,9 +193,35 @@ No Message ... waiting
202193

203194
Use the Priority Queue pattern when:
204195

205-
* The system must handle multiple tasks that might have different priorities.
206-
* Different users or tenants should be served with different priority.
196+
* You need to manage tasks or elements that have different priorities.
197+
* Applicable in scheduling systems where tasks need to be executed based on their priority.
198+
* Useful in scenarios where you need to handle a large number of elements with varying importance levels efficiently.
199+
200+
## Known Uses
201+
202+
* Task scheduling in operating systems.
203+
* Job scheduling in servers and batch processing systems.
204+
* Event simulation systems where events are processed based on their scheduled time.
205+
* Pathfinding algorithms (e.g., Dijkstra's or A* algorithms).
206+
207+
## Consequences
208+
209+
Benefits:
210+
211+
* Efficient management of elements based on priority.
212+
* Enhanced performance for priority-based access and removal operations.
213+
* Improved scalability in systems requiring prioritized task execution.
214+
215+
Trade-offs:
216+
217+
* Increased complexity in implementation and maintenance compared to simple queues.
218+
* Potential for higher memory usage due to the underlying data structures.
219+
* Requires careful synchronization in a multi-threaded environment to avoid concurrency issues.
220+
221+
## Related Patterns
222+
223+
* Observer: Can be used alongside Priority Queue to notify when elements with high priority are processed.
207224

208225
## Credits
209226

210-
* [Priority Queue pattern](https://docs.microsoft.com/en-us/azure/architecture/patterns/priority-queue)
227+
* [Priority Queue pattern - Microsoft](https://docs.microsoft.com/en-us/azure/architecture/patterns/priority-queue)

0 commit comments

Comments
 (0)