Producer Consumer Pattern
The Producer Consumer mode means that one is responsible for production and the other is responsible for consumption.
The core is that the producer securely hands the data to the consumer.
actual case
Overview of class information:
class name | illustrate |
---|---|
Main.java | general entry for the method |
ConsumerCakeThread.java | thread that consumes cake |
Table.java | table for cakes |
BlockingQueueTable.java | BlockingQueue implementation |
ProducerCakeThread.java | thread producing cake |
definition
- ConsumerCakeThread.java
package com.github.houbb.thread.learn.easy.learn.producer.consumer;
import java.util.Random;
public class ConsumerCakeThread extends Thread {
private String name;
private final Table table;
public ConsumerCakeThread(String name, Table table) {
super(name);
this.table = table;
}
@Override
public void run() {
Random random = new Random(1000L);
try {
while(true) {
Thread.sleep(random.nextInt(1000));
String cake = table.take();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
- Table.java
package com.github.houbb.thread.learn.easy.learn.producer.consumer;
/**
* @see BlockingQueueTable 可以被这个替换
*/
public class Table {
/**
* 存放蛋糕的数组
*/
private String[] cakeArray;
/**
* 头
*/
private int head;
/**
* 尾巴
*/
private int tail;
private int count;
private final int size;
public Table(int size) {
this.size = size;
cakeArray = new String[size];
this.head = 0;
this.tail = 0;
this.count = 0;
}
public synchronized void put(final String cakeName) throws InterruptedException {
while(count >= size) {
wait();
}
cakeArray[tail] = cakeName;
count++;
tail = (tail + 1) % size;
System.out.println(Thread.currentThread().getName() + " put cake " + cakeName);
notifyAll();
}
public synchronized String take() throws InterruptedException {
while (count <= 0) {
wait();
}
String result = cakeArray[head];
head = (head + 1) % size;
count--;
System.out.println(Thread.currentThread().getName() + " take cake " + result);
notifyAll();
return result;
}
}
- BlockingQueueTable.java
package com.github.houbb.thread.learn.easy.learn.producer.consumer;
import java.util.concurrent.ArrayBlockingQueue;
/**
* 使用 queue
*/
public class BlockingQueueTable extends ArrayBlockingQueue<String> {
public BlockingQueueTable(int size) {
super(size);
}
public void put(final String cakeName) throws InterruptedException {
super.put(cakeName);
}
public String take() throws InterruptedException {
return super.take();
}
}
- ProducerCakeThread.java
package com.github.houbb.thread.learn.easy.learn.producer.consumer;
import java.util.Random;
public class ProducerCakeThread extends Thread {
private final Table table;
private static int id = 0;
public ProducerCakeThread(String name, Table table) {
super(name);
this.table = table;
}
@Override
public void run() {
Random random = new Random(1000L);
try {
while(true) {
String cakeName = getName()+"-"+genId();
Thread.sleep(random.nextInt(1000));
table.put(cakeName);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private static synchronized int genId() {
return id++;
}
}
test
- Main.java
package com.github.houbb.thread.learn.easy.learn.producer.consumer;
public class Main {
public static void main(String[] args) {
Table table = new Table(3);
new ConsumerCakeThread("ConsumerCake", table).start();
new ProducerCakeThread("ProducerCake", table).start();
}
}
- Test Results
ProducerCake put cake ProducerCake-0
ConsumerCake take cake ProducerCake-0
ProducerCake put cake ProducerCake-1
ConsumerCake take cake ProducerCake-1
ProducerCake put cake ProducerCake-2
ConsumerCake take cake ProducerCake-2
ProducerCake put cake ProducerCake-3
ConsumerCake take cake ProducerCake-3
ProducerCake put cake ProducerCake-4
ConsumerCake take cake ProducerCake-4
ProducerCake put cake ProducerCake-5
ConsumerCake take cake ProducerCake-5
Method to realize
UML & Code
UML
The UML diagram is as follows
Code
code address