线程并发协作
应用场景
- 假设仓库中只能存放一定数量的产品,生产者将生产的产品放入仓库,消费者从仓库中取走产品消费。
- 如果仓库中没有产品,则生产者将产品放入仓库,否则停止生产并等待,知道仓库中的产品被消费者取走为止。
- 如果仓库中有产品,则消费者可以将产品取走消费,否则停止消费并等待,知道仓库中再次放入产品为止。
管程法
利用缓冲区进行处理
- 生产者:负责生产数据的模块
- 消费者:负责处理数据的模块
- 缓冲区:消费者不能直接使用生产者的数据,生产者将生产好的数据放入缓冲区,消费者从缓冲区消费数据。
代码示例如下:
/**
* @author caoyu
* TUDO:生产者类
* @version 1.0
* @date 2021/6/23 15:15
*/
public class Producer extends Thread{
Buffer buffer;
public Producer (Buffer buffer){
this.buffer = buffer;
}
@Override
public void run() {
//生产100个产品
for (int i = 0; i < 100; i++) {
buffer.push(new Product(i));
System.out.println("生产了第"+i+"个产品");
}
}
}
/**
* @author caoyu
* TUDO:消费者类
* @version 1.0
* @date 2021/6/23 15:15
*/
public class Consumer extends Thread{
Buffer buffer;
public Consumer (Buffer buffer){
this.buffer = buffer;
}
/**
* 消费
*/
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("消费了第"+buffer.pop().id+"个产品");
}
}
}
/**
* @author caoyu
* TUDO:产品类
* @version 1.0
* @date 2021/6/23 15:16
*/
public class Product {
int id;
public Product(int id) {
this.id = id;
}
}
/**
* @author caoyu
* TUDO:缓冲区
* @version 1.0
* @date 2021/6/23 15:17
*/
public class Buffer {
/** 缓冲区大小 **/
Product[] products = new Product[10];
/** 缓冲区计数器 **/
int count = 0;
/**
* 生产者放入产品
* @param product
*/
public synchronized void push(Product product){
// 判断容器是否满了
//此处应该使用while,别使用if,否则当有多个生产者时,会出现脏判断
while(count == products.length){
// 生产者等待
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//如何没有满,加入产品
products[count] = product;
count++;
//放入产品后,即可通知消费者进行消费
this.notifyAll();
}
/**
* 消费者消费产品
* @return product
*/
public synchronized Product pop(){
while(count == 0){
//消费者等待
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//开始消费
count--;
Product product = products[count];
//通知生产者开始生产。
this.notifyAll();
return product;
}
}
public static void main(String[] args) {
Buffer buffer = new Buffer();
new Producer(buffer).start();
new Consumer(buffer).start();
}
信号灯法
- 通过标识位进行标识,根据标识位的不同,通知对方进行消费或生产
代码示例如下:
/**
* @author caoyu
* TUDO:产品类
* @version 1.0
* @date 2021/6/23 15:16
*/
public class Product {
//生产者生产时,消费者等待
//消费者消费时,生产者等待
String productName;//产品名称
boolean flag = true;
//生产
public synchronized void produce(String productName){
while(!flag){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("生产者生产了:"+productName);
//通知消费者消费
this.notifyAll();
this.productName = productName;
this.flag = !flag;
}
//消费
public synchronized void consumption(){
while(flag){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("消费者消费了:"+productName);
this.notifyAll();
this.flag = !flag;
}
}
/**
* @author caoyu
* TUDO:生产者类
* @version 1.0
* @date 2021/6/23 15:15
*/
public class Producer extends Thread{
Product product;
public Producer(Product product){
this.product = product;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
this.product.produce("第"+i+"个产品");
}
}
}
/**
* @author caoyu
* TUDO:消费者类
* @version 1.0
* @date 2021/6/23 15:15
*/
public class Consumer extends Thread{
Product product;
public Consumer(Product product){
this.product = product;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
this.product.consumption();
}
}
}
public static void main(String[] args) {
Product product = new Product();
new Producer(product).start();
new Consumer(product).start();
}