Skip to content

Commit 7f6067f

Browse files
ranjeet-floydiluwatar
authored andcommitted
Added priority queue design pattern (iluwatar#888)
* added priority queue design pattern * Minor Refactored, fixed review comments
1 parent 11c0550 commit 7f6067f

File tree

10 files changed

+616
-7
lines changed

10 files changed

+616
-7
lines changed

pom.xml

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@
1717
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1818
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
1919
THE SOFTWARE.
20-
--><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
20+
-->
21+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
22+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
2123
<modelVersion>4.0.0</modelVersion>
2224
<groupId>com.iluwatar</groupId>
2325
<artifactId>java-design-patterns</artifactId>
@@ -162,12 +164,13 @@
162164
<module>trampoline</module>
163165
<module>serverless</module>
164166
<module>ambassador</module>
165-
<module>acyclic-visitor</module>
166-
<module>collection-pipeline</module>
167-
<module>master-worker-pattern</module>
168-
<module>spatial-partition</module>
169-
<module>commander</module>
170-
<module>typeobjectpattern</module>
167+
<module>acyclic-visitor</module>
168+
<module>collection-pipeline</module>
169+
<module>master-worker-pattern</module>
170+
<module>spatial-partition</module>
171+
<module>priority-queue</module>
172+
<module>commander</module>
173+
<module>typeobjectpattern</module>
171174
</modules>
172175

173176
<repositories>

priority-queue/README.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
---
2+
layout: pattern
3+
title: Priority Queue Pattern
4+
folder: priority-queue
5+
permalink: /patterns/priority-queue/
6+
categories: Behavioral
7+
tags:
8+
- Java
9+
- Difficulty-Beginner
10+
---
11+
12+
## 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.
14+
15+
## 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.
17+
18+
## Applicability
19+
Use the Property pattern when
20+
21+
* The system must handle multiple tasks that might have different priorities.
22+
* Different users or tenants should be served with different priority..
23+
24+
## Real world examples
25+
26+
* [ Priority Queue Pattern](https://docs.microsoft.com/en-us/previous-versions/msp-n-p/dn589794(v=pandp.10))
27+
Microsoft Azure does not provide a queuing mechanism that natively support automatic prioritization of messages through sorting. However, it does provide Azure Service Bus topics and subscriptions, which support a queuing mechanism that provides message filtering, together with a wide range of flexible capabilities that make it ideal for use in almost all priority queue implementations.

priority-queue/pom.xml

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
4+
The MIT License
5+
Copyright (c) 2014 Ilkka Seppälä
6+
7+
Permission is hereby granted, free of charge, to any person obtaining a copy
8+
of this software and associated documentation files (the "Software"), to deal
9+
in the Software without restriction, including without limitation the rights
10+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11+
copies of the Software, and to permit persons to whom the Software is
12+
furnished to do so, subject to the following conditions:
13+
14+
The above copyright notice and this permission notice shall be included in
15+
all copies or substantial portions of the Software.
16+
17+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23+
THE SOFTWARE.
24+
25+
-->
26+
<project xmlns="http://maven.apache.org/POM/4.0.0"
27+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
28+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
29+
<modelVersion>4.0.0</modelVersion>
30+
<artifactId>priority-queue</artifactId>
31+
<parent>
32+
<groupId>com.iluwatar</groupId>
33+
<artifactId>java-design-patterns</artifactId>
34+
<version>1.21.0-SNAPSHOT</version>
35+
</parent>
36+
37+
<dependencies>
38+
<dependency>
39+
<groupId>org.junit.jupiter</groupId>
40+
<artifactId>junit-jupiter-engine</artifactId>
41+
<scope>test</scope>
42+
</dependency>
43+
</dependencies>
44+
45+
</project>
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/**
2+
* The MIT License
3+
* Copyright (c) 2014 Ilkka Seppälä
4+
* <p>
5+
* Permission is hereby granted, free of charge, to any person obtaining a copy
6+
* of this software and associated documentation files (the "Software"), to deal
7+
* in the Software without restriction, including without limitation the rights
8+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
* copies of the Software, and to permit persons to whom the Software is
10+
* furnished to do so, subject to the following conditions:
11+
* <p>
12+
* The above copyright notice and this permission notice shall be included in
13+
* all copies or substantial portions of the Software.
14+
* <p>
15+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
* THE SOFTWARE.
22+
*/
23+
package com.iluwatar.priority.queue;
24+
25+
/**
26+
* Prioritize requests sent to services so that requests with a higher priority are received and
27+
* processed more quickly than those of a lower priority.
28+
* This pattern is useful in applications that offer different service level guarantees
29+
* to individual clients.
30+
* Example :Send multiple message with different priority to worker queue.
31+
* Worker execute higher priority message first
32+
* @see "https://docs.microsoft.com/en-us/previous-versions/msp-n-p/dn589794(v=pandp.10)"
33+
*/
34+
public class Application {
35+
/**
36+
* main entry
37+
*/
38+
public static void main(String[] args) throws Exception {
39+
40+
QueueManager queueManager = new QueueManager(100);
41+
42+
// push some message to queue
43+
// Low Priority message
44+
for (int i = 0; i < 100; i++) {
45+
queueManager.publishMessage(new Message("Low Message Priority", 0));
46+
}
47+
48+
// High Priority message
49+
for (int i = 0; i < 100; i++) {
50+
queueManager.publishMessage(new Message("High Message Priority", 1));
51+
}
52+
53+
54+
// run worker
55+
Worker worker = new Worker(queueManager);
56+
worker.run();
57+
58+
59+
}
60+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/**
2+
* The MIT License
3+
* Copyright (c) 2014 Ilkka Seppälä
4+
*
5+
* Permission is hereby granted, free of charge, to any person obtaining a copy
6+
* of this software and associated documentation files (the "Software"), to deal
7+
* in the Software without restriction, including without limitation the rights
8+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
* copies of the Software, and to permit persons to whom the Software is
10+
* furnished to do so, subject to the following conditions:
11+
*
12+
* The above copyright notice and this permission notice shall be included in
13+
* all copies or substantial portions of the Software.
14+
*
15+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
* THE SOFTWARE.
22+
*/
23+
package com.iluwatar.priority.queue;
24+
25+
/**
26+
* Message bean
27+
*/
28+
public class Message implements Comparable<Message> {
29+
private final String message;
30+
private final int priority; // define message priority in queue
31+
32+
33+
public Message(String message, int priority) {
34+
this.message = message;
35+
this.priority = priority;
36+
}
37+
38+
@Override
39+
public int compareTo(Message o) {
40+
return priority - o.priority;
41+
}
42+
43+
@Override
44+
public String toString() {
45+
return "Message{"
46+
+ "message='" + message + '\''
47+
+ ", priority=" + priority
48+
+ '}';
49+
}
50+
}
Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
/**
2+
* The MIT License
3+
* Copyright (c) 2014 Ilkka Seppälä
4+
* <p>
5+
* Permission is hereby granted, free of charge, to any person obtaining a copy
6+
* of this software and associated documentation files (the "Software"), to deal
7+
* in the Software without restriction, including without limitation the rights
8+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
* copies of the Software, and to permit persons to whom the Software is
10+
* furnished to do so, subject to the following conditions:
11+
* <p>
12+
* The above copyright notice and this permission notice shall be included in
13+
* all copies or substantial portions of the Software.
14+
* <p>
15+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
* THE SOFTWARE.
22+
*/
23+
package com.iluwatar.priority.queue;
24+
25+
import org.slf4j.Logger;
26+
import org.slf4j.LoggerFactory;
27+
28+
import static java.util.Arrays.copyOf;
29+
30+
/**
31+
* Keep high Priority message on top using maxHeap.
32+
*
33+
* @param <T> : DataType to push in Queue
34+
*/
35+
public class PriorityMessageQueue<T extends Comparable> {
36+
37+
private static final Logger LOGGER = LoggerFactory.getLogger(PriorityMessageQueue.class);
38+
39+
private int size = 0;
40+
41+
private int capacity;
42+
43+
44+
private T[] queue;
45+
46+
public PriorityMessageQueue(T[] queue) {
47+
this.queue = queue;
48+
this.capacity = queue.length;
49+
}
50+
51+
/**
52+
* Remove top message from queue
53+
*/
54+
public T remove() {
55+
if (isEmpty()) {
56+
return null;
57+
}
58+
59+
T root = queue[0];
60+
queue[0] = queue[size - 1];
61+
size--;
62+
maxHeapifyDown();
63+
return root;
64+
}
65+
66+
/**
67+
* Add message to queue
68+
*/
69+
public void add(T t) {
70+
ensureCapacity();
71+
queue[size] = t;
72+
size++;
73+
maxHeapifyUp();
74+
}
75+
76+
/**
77+
* Check queue size
78+
*/
79+
public boolean isEmpty() {
80+
return size == 0;
81+
}
82+
83+
84+
private void maxHeapifyDown() {
85+
int index = 0;
86+
while (hasLeftChild(index)) {
87+
88+
int smallerIndex = leftChildIndex(index);
89+
90+
if (hasRightChild(index) && right(index).compareTo(left(index)) > 0) {
91+
smallerIndex = rightChildIndex(index);
92+
}
93+
94+
if (queue[index].compareTo(queue[smallerIndex]) > 0) {
95+
break;
96+
} else {
97+
swap(index, smallerIndex);
98+
}
99+
100+
index = smallerIndex;
101+
102+
103+
}
104+
105+
}
106+
107+
private void maxHeapifyUp() {
108+
int index = size - 1;
109+
while (hasParent(index) && parent(index).compareTo(queue[index]) < 0) {
110+
swap(parentIndex(index), index);
111+
index = parentIndex(index);
112+
}
113+
}
114+
115+
116+
// index
117+
private int parentIndex(int pos) {
118+
return (pos - 1) / 2;
119+
}
120+
121+
private int leftChildIndex(int parentPos) {
122+
return 2 * parentPos + 1;
123+
}
124+
125+
private int rightChildIndex(int parentPos) {
126+
return 2 * parentPos + 2;
127+
}
128+
129+
// value
130+
private T parent(int childIndex) {
131+
return queue[parentIndex(childIndex)];
132+
}
133+
134+
private T left(int parentIndex) {
135+
return queue[leftChildIndex(parentIndex)];
136+
}
137+
138+
private T right(int parentIndex) {
139+
return queue[rightChildIndex(parentIndex)];
140+
}
141+
142+
// check
143+
private boolean hasLeftChild(int index) {
144+
return leftChildIndex(index) < size;
145+
}
146+
147+
private boolean hasRightChild(int index) {
148+
return rightChildIndex(index) < size;
149+
}
150+
151+
private boolean hasParent(int index) {
152+
return parentIndex(index) >= 0;
153+
}
154+
155+
private void swap(int fpos, int tpos) {
156+
T tmp = queue[fpos];
157+
queue[fpos] = queue[tpos];
158+
queue[tpos] = tmp;
159+
}
160+
161+
private void ensureCapacity() {
162+
if (size == capacity) {
163+
capacity = capacity * 2;
164+
queue = copyOf(queue, capacity);
165+
}
166+
}
167+
168+
/**
169+
* For debug .. print current state of queue
170+
*/
171+
public void print() {
172+
for (int i = 0; i <= size / 2; i++) {
173+
LOGGER.info(" PARENT : " + queue[i] + " LEFT CHILD : "
174+
+ left(i) + " RIGHT CHILD :" + right(i));
175+
}
176+
}
177+
178+
}

0 commit comments

Comments
 (0)