Skip to content

Commit 82842d6

Browse files
committed
Update README.md
1 parent 9b71479 commit 82842d6

File tree

3 files changed

+192
-9
lines changed

3 files changed

+192
-9
lines changed

priority-queue/README.md

+188-4
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,203 @@ tags:
1010
---
1111

1212
## Intent
13-
Prioritize requests sent to services so that requests with a higher priority are received and processed more quickly than those of a lower priority. This pattern is useful in applications that offer different service level guarantees to individual clients.
13+
14+
Prioritize requests sent to services so that requests with a higher priority are received and
15+
processed more quickly than those of a lower priority. This pattern is useful in applications that
16+
offer different service level guarantees to individual clients.
1417

1518
## Explanation
16-
Applications may delegate specific tasks to other services; for example, to perform background processing or to integrate with other applications or services. In the cloud, a message queue is typically used to delegate tasks to background processing. In many cases the order in which requests are received by a service is not important. However, in some cases it may be necessary to prioritize specific requests. These requests should be processed earlier than others of a lower priority that may have been sent previously by the application.
19+
20+
Applications may delegate specific tasks to other services; for example, to perform background
21+
processing or to integrate with other applications or services. In the cloud, a message queue is
22+
typically used to delegate tasks to background processing. In many cases the order in which requests
23+
are received by a service is not important. However, in some cases it may be necessary to prioritize
24+
specific requests. These requests should be processed earlier than others of a lower priority that
25+
may have been sent previously by the application.
26+
27+
Real world example
28+
29+
> Imagine a video processing service with free and premium customers. The requests coming from the
30+
> paying premium customers should be prioritized over the others.
31+
32+
In plain words
33+
34+
> Priority Queue enables processing of high priority messages first, regardless of queue size or
35+
> message age.
36+
37+
Wikipedia says
38+
39+
> In computer science, a priority queue is an abstract data type similar to regular queue or stack
40+
> data structure in which each element additionally has a "priority" associated with it. In a
41+
> priority queue, an element with high priority is served before an element with low priority.
42+
43+
**Programmatic Example**
44+
45+
Looking at the video processing example from above, let's first see the `Message` structure.
46+
47+
```java
48+
public class Message implements Comparable<Message> {
49+
50+
private final String message;
51+
private final int priority; // define message priority in queue
52+
53+
public Message(String message, int priority) {
54+
this.message = message;
55+
this.priority = priority;
56+
}
57+
58+
@Override
59+
public int compareTo(Message o) {
60+
return priority - o.priority;
61+
}
62+
...
63+
}
64+
```
65+
66+
Here's `PriorityMessageQueue` that handles storing the messages and serving them in priority
67+
order.
68+
69+
```java
70+
public class PriorityMessageQueue<T extends Comparable> {
71+
72+
...
73+
74+
public T remove() {
75+
if (isEmpty()) {
76+
return null;
77+
}
78+
79+
final var root = queue[0];
80+
queue[0] = queue[size - 1];
81+
size--;
82+
maxHeapifyDown();
83+
return root;
84+
}
85+
86+
public void add(T t) {
87+
ensureCapacity();
88+
queue[size] = t;
89+
size++;
90+
maxHeapifyUp();
91+
}
92+
93+
...
94+
}
95+
```
96+
97+
`QueueManager` has a `PriorityMessageQueue` and makes it easy to `publishMessage` and
98+
`receiveMessage`.
99+
100+
```java
101+
public class QueueManager {
102+
103+
private final PriorityMessageQueue<Message> messagePriorityMessageQueue;
104+
105+
public QueueManager(int initialCapacity) {
106+
messagePriorityMessageQueue = new PriorityMessageQueue<>(new Message[initialCapacity]);
107+
}
108+
109+
public void publishMessage(Message message) {
110+
messagePriorityMessageQueue.add(message);
111+
}
112+
113+
public Message receiveMessage() {
114+
if (messagePriorityMessageQueue.isEmpty()) {
115+
return null;
116+
}
117+
return messagePriorityMessageQueue.remove();
118+
}
119+
}
120+
```
121+
122+
`Worker` constantly polls `QueueManager` for highest priority message and processes it.
123+
124+
```java
125+
public class Worker {
126+
127+
private static final Logger LOGGER = LoggerFactory.getLogger(Worker.class);
128+
129+
private final QueueManager queueManager;
130+
131+
public Worker(QueueManager queueManager) {
132+
this.queueManager = queueManager;
133+
}
134+
135+
public void run() throws Exception {
136+
while (true) {
137+
var message = queueManager.receiveMessage();
138+
if (message == null) {
139+
LOGGER.info("No Message ... waiting");
140+
Thread.sleep(200);
141+
} else {
142+
processMessage(message);
143+
}
144+
}
145+
}
146+
147+
private void processMessage(Message message) {
148+
LOGGER.info(message.toString());
149+
}
150+
}
151+
```
152+
153+
Here's the full example how we create an instance of `QueueManager` and process messages using
154+
`Worker`.
155+
156+
```java
157+
var queueManager = new QueueManager(100);
158+
159+
for (var i = 0; i < 100; i++) {
160+
queueManager.publishMessage(new Message("Low Message Priority", 0));
161+
}
162+
163+
for (var i = 0; i < 100; i++) {
164+
queueManager.publishMessage(new Message("High Message Priority", 1));
165+
}
166+
167+
var worker = new Worker(queueManager);
168+
worker.run();
169+
```
170+
171+
Program output:
172+
173+
```
174+
Message{message='High Message Priority', priority=1}
175+
Message{message='High Message Priority', priority=1}
176+
Message{message='High Message Priority', priority=1}
177+
Message{message='High Message Priority', priority=1}
178+
Message{message='High Message Priority', priority=1}
179+
Message{message='High Message Priority', priority=1}
180+
Message{message='High Message Priority', priority=1}
181+
Message{message='High Message Priority', priority=1}
182+
Message{message='High Message Priority', priority=1}
183+
Message{message='High Message Priority', priority=1}
184+
Message{message='Low Message Priority', priority=0}
185+
Message{message='Low Message Priority', priority=0}
186+
Message{message='Low Message Priority', priority=0}
187+
Message{message='Low Message Priority', priority=0}
188+
Message{message='Low Message Priority', priority=0}
189+
Message{message='Low Message Priority', priority=0}
190+
Message{message='Low Message Priority', priority=0}
191+
Message{message='Low Message Priority', priority=0}
192+
Message{message='Low Message Priority', priority=0}
193+
Message{message='Low Message Priority', priority=0}
194+
No Message ... waiting
195+
No Message ... waiting
196+
No Message ... waiting
197+
```
198+
17199

18200
## Class diagram
201+
19202
![alt text](./etc/priority-queue.urm.png "Priority Queue pattern class diagram")
20203

21204
## Applicability
22-
Use the Priority Queue pattern when
205+
206+
Use the Priority Queue pattern when:
23207

24208
* The system must handle multiple tasks that might have different priorities.
25-
* Different users or tenants should be served with different priority..
209+
* Different users or tenants should be served with different priority.
26210

27211
## Credits
28212

priority-queue/src/main/java/com/iluwatar/priority/queue/Application.java

+3-4
Original file line numberDiff line numberDiff line change
@@ -37,20 +37,19 @@ public class Application {
3737
*/
3838
public static void main(String[] args) throws Exception {
3939

40-
var queueManager = new QueueManager(100);
40+
var queueManager = new QueueManager(10);
4141

4242
// push some message to queue
4343
// Low Priority message
44-
for (var i = 0; i < 100; i++) {
44+
for (var i = 0; i < 10; i++) {
4545
queueManager.publishMessage(new Message("Low Message Priority", 0));
4646
}
4747

4848
// High Priority message
49-
for (var i = 0; i < 100; i++) {
49+
for (var i = 0; i < 10; i++) {
5050
queueManager.publishMessage(new Message("High Message Priority", 1));
5151
}
5252

53-
5453
// run worker
5554
var worker = new Worker(queueManager);
5655
worker.run();

priority-queue/src/main/java/com/iluwatar/priority/queue/QueueManager.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ public void publishMessage(Message message) {
4545

4646

4747
/**
48-
* recive message from queue.
48+
* Receive message from queue.
4949
*/
5050
public Message receiveMessage() {
5151
if (messagePriorityMessageQueue.isEmpty()) {

0 commit comments

Comments
 (0)