Skip to content

Commit 3dc9b2f

Browse files
committed
Merge pull request iluwatar#276 from hoswey/master
iluwatar#271 implements producer-consumer
2 parents a869294 + 07faa2f commit 3dc9b2f

File tree

11 files changed

+299
-0
lines changed

11 files changed

+299
-0
lines changed

pom.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
<module>execute-around</module>
5757
<module>property</module>
5858
<module>intercepting-filter</module>
59+
<module>producer-consumer</module>
5960
<module>poison-pill</module>
6061
<module>lazy-loading</module>
6162
<module>service-layer</module>
26.5 KB
Loading
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<class-diagram version="1.1.8" icons="true" automaticImage="PNG" always-add-relationships="false" generalizations="true"
3+
realizations="true" associations="true" dependencies="false" nesting-relationships="true">
4+
<class id="1" language="java" name="com.iluwatar.producer.consumer.Item" project="producer-consumer"
5+
file="/producer-consumer/src/main/java/com/iluwatar/producer/consumer/Item.java" binary="false"
6+
corner="BOTTOM_RIGHT">
7+
<position height="-1" width="-1" x="415" y="378"/>
8+
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
9+
sort-features="false" accessors="true" visibility="true">
10+
<attributes public="true" package="true" protected="true" private="true" static="true"/>
11+
<operations public="true" package="true" protected="true" private="true" static="true"/>
12+
</display>
13+
</class>
14+
<class id="2" language="java" name="com.iluwatar.producer.consumer.Producer" project="producer-consumer"
15+
file="/producer-consumer/src/main/java/com/iluwatar/producer/consumer/Producer.java" binary="false"
16+
corner="BOTTOM_RIGHT">
17+
<position height="-1" width="-1" x="150" y="191"/>
18+
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
19+
sort-features="false" accessors="true" visibility="true">
20+
<attributes public="true" package="true" protected="true" private="true" static="true"/>
21+
<operations public="true" package="true" protected="true" private="true" static="true"/>
22+
</display>
23+
</class>
24+
<class id="3" language="java" name="com.iluwatar.producer.consumer.Consumer" project="producer-consumer"
25+
file="/producer-consumer/src/main/java/com/iluwatar/producer/consumer/Consumer.java" binary="false"
26+
corner="BOTTOM_RIGHT">
27+
<position height="-1" width="-1" x="675" y="186"/>
28+
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
29+
sort-features="false" accessors="true" visibility="true">
30+
<attributes public="true" package="true" protected="true" private="true" static="true"/>
31+
<operations public="true" package="true" protected="true" private="true" static="true"/>
32+
</display>
33+
</class>
34+
<class id="4" language="java" name="com.iluwatar.producer.consumer.ItemQueue" project="producer-consumer"
35+
file="/producer-consumer/src/main/java/com/iluwatar/producer/consumer/ItemQueue.java" binary="false"
36+
corner="BOTTOM_RIGHT">
37+
<position height="-1" width="-1" x="415" y="187"/>
38+
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
39+
sort-features="false" accessors="true" visibility="true">
40+
<attributes public="true" package="true" protected="true" private="true" static="true"/>
41+
<operations public="true" package="true" protected="true" private="true" static="true"/>
42+
</display>
43+
</class>
44+
<association id="5">
45+
<end type="SOURCE" refId="3" navigable="false">
46+
<attribute id="6" name="queue"/>
47+
<multiplicity id="7" minimum="0" maximum="1"/>
48+
</end>
49+
<end type="TARGET" refId="4" navigable="true"/>
50+
<display labels="true" multiplicity="true"/>
51+
</association>
52+
<association id="8">
53+
<end type="SOURCE" refId="4" navigable="false">
54+
<attribute id="9" name="queue"/>
55+
<multiplicity id="10" minimum="0" maximum="2147483647"/>
56+
</end>
57+
<end type="TARGET" refId="1" navigable="true"/>
58+
<display labels="true" multiplicity="true"/>
59+
</association>
60+
<association id="11">
61+
<end type="SOURCE" refId="2" navigable="false">
62+
<attribute id="12" name="queue"/>
63+
<multiplicity id="13" minimum="0" maximum="1"/>
64+
</end>
65+
<end type="TARGET" refId="4" navigable="true"/>
66+
<display labels="true" multiplicity="true"/>
67+
</association>
68+
<classifier-display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
69+
sort-features="false" accessors="true" visibility="true">
70+
<attributes public="true" package="true" protected="true" private="true" static="true"/>
71+
<operations public="true" package="true" protected="true" private="true" static="true"/>
72+
</classifier-display>
73+
<association-display labels="true" multiplicity="true"/>
74+
</class-diagram>

producer-consumer/index.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
---
2+
layout: pattern
3+
title: Producer Consumer
4+
folder: producer-consumer
5+
permalink: /patterns/producer-consumer/
6+
categories: Other
7+
tags: Java
8+
---
9+
10+
**Intent:** Producer Consumer Design pattern is a classic concurrency or threading pattern which reduces
11+
coupling between Producer and Consumer by separating Identification of work with Execution of
12+
Work..
13+
14+
15+
16+
![alt text](./etc/producer-consumer.png "Producer Consumer")
17+
18+
**Applicability:** Use the Producer Consumer idiom when
19+
20+
* decouple system by separate work in two process produce and consume.
21+
* addresses the issue of different timing require to produce work or consuming work
22+

producer-consumer/pom.xml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?xml version="1.0"?>
2+
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
4+
<modelVersion>4.0.0</modelVersion>
5+
<parent>
6+
<groupId>com.iluwatar</groupId>
7+
<artifactId>java-design-patterns</artifactId>
8+
<version>1.7.0</version>
9+
</parent>
10+
<artifactId>producer-consumer</artifactId>
11+
<dependencies>
12+
<dependency>
13+
<groupId>junit</groupId>
14+
<artifactId>junit</artifactId>
15+
<scope>test</scope>
16+
</dependency>
17+
</dependencies>
18+
</project>
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package com.iluwatar.producer.consumer;
2+
3+
import java.util.concurrent.ExecutorService;
4+
import java.util.concurrent.Executors;
5+
import java.util.concurrent.TimeUnit;
6+
7+
/**
8+
* Producer Consumer Design pattern is a classic concurrency or threading pattern which reduces
9+
* coupling between Producer and Consumer by separating Identification of work with Execution of
10+
* Work.
11+
* <p>
12+
* In producer consumer design pattern a shared queue is used to control the flow and this
13+
* separation allows you to code producer and consumer separately. It also addresses the issue of
14+
* different timing require to produce item or consuming item. by using producer consumer pattern
15+
* both Producer and Consumer Thread can work with different speed.
16+
*
17+
*/
18+
public class App {
19+
20+
/**
21+
* Program entry point
22+
*
23+
* @param args command line args
24+
*/
25+
public static void main(String[] args) {
26+
27+
ItemQueue queue = new ItemQueue();
28+
29+
ExecutorService executorService = Executors.newFixedThreadPool(5);
30+
for (int i = 0; i < 2; i++) {
31+
32+
final Producer producer = new Producer("Producer_" + i, queue);
33+
executorService.submit(() -> {
34+
while (true) {
35+
producer.produce();
36+
}
37+
});
38+
};
39+
40+
for (int i = 0; i < 3; i++) {
41+
final Consumer consumer = new Consumer("Consumer_" + i, queue);
42+
executorService.submit(() -> {
43+
while (true) {
44+
consumer.consume();
45+
}
46+
});
47+
}
48+
49+
executorService.shutdown();
50+
try {
51+
executorService.awaitTermination(10, TimeUnit.SECONDS);
52+
executorService.shutdownNow();
53+
} catch (InterruptedException e) {
54+
System.out.println("Error waiting for ExecutorService shutdown");
55+
}
56+
}
57+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package com.iluwatar.producer.consumer;
2+
3+
/**
4+
* Class responsible for consume the {@link Item} produced by {@link Producer}
5+
*/
6+
public class Consumer {
7+
8+
private final ItemQueue queue;
9+
10+
private final String name;
11+
12+
public Consumer(String name, ItemQueue queue) {
13+
this.name = name;
14+
this.queue = queue;
15+
}
16+
17+
public void consume() throws InterruptedException {
18+
19+
Item item = queue.take();
20+
System.out.println(String.format("Consumer [%s] consume item [%s] produced by [%s]", name,
21+
item.getId(), item.getProducer()));
22+
23+
}
24+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package com.iluwatar.producer.consumer;
2+
3+
/**
4+
* Class take part of an {@link Producer}-{@link Consumer} exchange.
5+
*/
6+
public class Item {
7+
8+
private String producer;
9+
10+
private int id;
11+
12+
public Item(String producer, int id) {
13+
this.id = id;
14+
this.producer = producer;
15+
}
16+
17+
public int getId() {
18+
19+
return id;
20+
}
21+
22+
public String getProducer() {
23+
24+
return producer;
25+
}
26+
27+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package com.iluwatar.producer.consumer;
2+
3+
import java.util.concurrent.LinkedBlockingQueue;
4+
5+
/**
6+
* Class as a channel for {@link Producer}-{@link Consumer} exchange.
7+
*/
8+
public class ItemQueue {
9+
10+
private LinkedBlockingQueue<Item> queue;
11+
12+
public ItemQueue() {
13+
14+
queue = new LinkedBlockingQueue<Item>(5);
15+
}
16+
17+
public void put(Item item) throws InterruptedException {
18+
19+
queue.put(item);
20+
}
21+
22+
public Item take() throws InterruptedException {
23+
24+
return queue.take();
25+
}
26+
27+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package com.iluwatar.producer.consumer;
2+
3+
import java.util.Random;
4+
5+
/**
6+
* Class responsible for producing unit of work that can be expressed as {@link Item} and submitted
7+
* to queue
8+
*/
9+
public class Producer {
10+
11+
private final ItemQueue queue;
12+
13+
private final String name;
14+
15+
private int itemId = 0;
16+
17+
public Producer(String name, ItemQueue queue) {
18+
this.name = name;
19+
this.queue = queue;
20+
}
21+
22+
public void produce() throws InterruptedException {
23+
24+
Item item = new Item(name, itemId++);
25+
queue.put(item);
26+
Random random = new Random();
27+
Thread.sleep(random.nextInt(2000));
28+
}
29+
}

0 commit comments

Comments
 (0)