Update README.md
This commit is contained in:
parent
9b71479d04
commit
82842d614b
@ -10,19 +10,203 @@ tags:
|
|||||||
---
|
---
|
||||||
|
|
||||||
## Intent
|
## Intent
|
||||||
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.
|
|
||||||
|
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.
|
||||||
|
|
||||||
## Explanation
|
## Explanation
|
||||||
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.
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
Real world example
|
||||||
|
|
||||||
|
> Imagine a video processing service with free and premium customers. The requests coming from the
|
||||||
|
> paying premium customers should be prioritized over the others.
|
||||||
|
|
||||||
|
In plain words
|
||||||
|
|
||||||
|
> Priority Queue enables processing of high priority messages first, regardless of queue size or
|
||||||
|
> message age.
|
||||||
|
|
||||||
|
Wikipedia says
|
||||||
|
|
||||||
|
> 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.
|
||||||
|
|
||||||
|
**Programmatic Example**
|
||||||
|
|
||||||
|
Looking at the video processing example from above, let's first see the `Message` structure.
|
||||||
|
|
||||||
|
```java
|
||||||
|
public class Message implements Comparable<Message> {
|
||||||
|
|
||||||
|
private final String message;
|
||||||
|
private final int priority; // define message priority in queue
|
||||||
|
|
||||||
|
public Message(String message, int priority) {
|
||||||
|
this.message = message;
|
||||||
|
this.priority = priority;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(Message o) {
|
||||||
|
return priority - o.priority;
|
||||||
|
}
|
||||||
|
...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Here's `PriorityMessageQueue` that handles storing the messages and serving them in priority
|
||||||
|
order.
|
||||||
|
|
||||||
|
```java
|
||||||
|
public class PriorityMessageQueue<T extends Comparable> {
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
public T remove() {
|
||||||
|
if (isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final var root = queue[0];
|
||||||
|
queue[0] = queue[size - 1];
|
||||||
|
size--;
|
||||||
|
maxHeapifyDown();
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void add(T t) {
|
||||||
|
ensureCapacity();
|
||||||
|
queue[size] = t;
|
||||||
|
size++;
|
||||||
|
maxHeapifyUp();
|
||||||
|
}
|
||||||
|
|
||||||
|
...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`QueueManager` has a `PriorityMessageQueue` and makes it easy to `publishMessage` and
|
||||||
|
`receiveMessage`.
|
||||||
|
|
||||||
|
```java
|
||||||
|
public class QueueManager {
|
||||||
|
|
||||||
|
private final PriorityMessageQueue<Message> messagePriorityMessageQueue;
|
||||||
|
|
||||||
|
public QueueManager(int initialCapacity) {
|
||||||
|
messagePriorityMessageQueue = new PriorityMessageQueue<>(new Message[initialCapacity]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void publishMessage(Message message) {
|
||||||
|
messagePriorityMessageQueue.add(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Message receiveMessage() {
|
||||||
|
if (messagePriorityMessageQueue.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return messagePriorityMessageQueue.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`Worker` constantly polls `QueueManager` for highest priority message and processes it.
|
||||||
|
|
||||||
|
```java
|
||||||
|
public class Worker {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = LoggerFactory.getLogger(Worker.class);
|
||||||
|
|
||||||
|
private final QueueManager queueManager;
|
||||||
|
|
||||||
|
public Worker(QueueManager queueManager) {
|
||||||
|
this.queueManager = queueManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run() throws Exception {
|
||||||
|
while (true) {
|
||||||
|
var message = queueManager.receiveMessage();
|
||||||
|
if (message == null) {
|
||||||
|
LOGGER.info("No Message ... waiting");
|
||||||
|
Thread.sleep(200);
|
||||||
|
} else {
|
||||||
|
processMessage(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processMessage(Message message) {
|
||||||
|
LOGGER.info(message.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Here's the full example how we create an instance of `QueueManager` and process messages using
|
||||||
|
`Worker`.
|
||||||
|
|
||||||
|
```java
|
||||||
|
var queueManager = new QueueManager(100);
|
||||||
|
|
||||||
|
for (var i = 0; i < 100; i++) {
|
||||||
|
queueManager.publishMessage(new Message("Low Message Priority", 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < 100; i++) {
|
||||||
|
queueManager.publishMessage(new Message("High Message Priority", 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
var worker = new Worker(queueManager);
|
||||||
|
worker.run();
|
||||||
|
```
|
||||||
|
|
||||||
|
Program output:
|
||||||
|
|
||||||
|
```
|
||||||
|
Message{message='High Message Priority', priority=1}
|
||||||
|
Message{message='High Message Priority', priority=1}
|
||||||
|
Message{message='High Message Priority', priority=1}
|
||||||
|
Message{message='High Message Priority', priority=1}
|
||||||
|
Message{message='High Message Priority', priority=1}
|
||||||
|
Message{message='High Message Priority', priority=1}
|
||||||
|
Message{message='High Message Priority', priority=1}
|
||||||
|
Message{message='High Message Priority', priority=1}
|
||||||
|
Message{message='High Message Priority', priority=1}
|
||||||
|
Message{message='High Message Priority', priority=1}
|
||||||
|
Message{message='Low Message Priority', priority=0}
|
||||||
|
Message{message='Low Message Priority', priority=0}
|
||||||
|
Message{message='Low Message Priority', priority=0}
|
||||||
|
Message{message='Low Message Priority', priority=0}
|
||||||
|
Message{message='Low Message Priority', priority=0}
|
||||||
|
Message{message='Low Message Priority', priority=0}
|
||||||
|
Message{message='Low Message Priority', priority=0}
|
||||||
|
Message{message='Low Message Priority', priority=0}
|
||||||
|
Message{message='Low Message Priority', priority=0}
|
||||||
|
Message{message='Low Message Priority', priority=0}
|
||||||
|
No Message ... waiting
|
||||||
|
No Message ... waiting
|
||||||
|
No Message ... waiting
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
## Class diagram
|
## Class diagram
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
## Applicability
|
## Applicability
|
||||||
Use the Priority Queue pattern when
|
|
||||||
|
Use the Priority Queue pattern when:
|
||||||
|
|
||||||
* The system must handle multiple tasks that might have different priorities.
|
* The system must handle multiple tasks that might have different priorities.
|
||||||
* Different users or tenants should be served with different priority..
|
* Different users or tenants should be served with different priority.
|
||||||
|
|
||||||
## Credits
|
## Credits
|
||||||
|
|
||||||
|
@ -37,20 +37,19 @@ public class Application {
|
|||||||
*/
|
*/
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
|
|
||||||
var queueManager = new QueueManager(100);
|
var queueManager = new QueueManager(10);
|
||||||
|
|
||||||
// push some message to queue
|
// push some message to queue
|
||||||
// Low Priority message
|
// Low Priority message
|
||||||
for (var i = 0; i < 100; i++) {
|
for (var i = 0; i < 10; i++) {
|
||||||
queueManager.publishMessage(new Message("Low Message Priority", 0));
|
queueManager.publishMessage(new Message("Low Message Priority", 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
// High Priority message
|
// High Priority message
|
||||||
for (var i = 0; i < 100; i++) {
|
for (var i = 0; i < 10; i++) {
|
||||||
queueManager.publishMessage(new Message("High Message Priority", 1));
|
queueManager.publishMessage(new Message("High Message Priority", 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// run worker
|
// run worker
|
||||||
var worker = new Worker(queueManager);
|
var worker = new Worker(queueManager);
|
||||||
worker.run();
|
worker.run();
|
||||||
|
@ -45,7 +45,7 @@ public class QueueManager {
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* recive message from queue.
|
* Receive message from queue.
|
||||||
*/
|
*/
|
||||||
public Message receiveMessage() {
|
public Message receiveMessage() {
|
||||||
if (messagePriorityMessageQueue.isEmpty()) {
|
if (messagePriorityMessageQueue.isEmpty()) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user