线程协作
线程协作
-
生产者消费者
应用场景 : 生产者和消费者问题
- 假设仓库中只能存放一件产品 , 生产者将生产出来的产品放入仓库 , 消费者将仓库中产品取走消费 .
- 如果仓库中没有产品 , 则生产者将产品放入仓库 , 否则停止生产并等待 , 直到仓库中的产品被消费者取走为止 .
- 如果仓库中放有产品 , 则消费者可以将产品取走消费 , 否则停止消费并等待 ,直到仓库中再次放入产品为止。
-
这是一个线程同步问题 , 生产者和消费者共享同一个资源 , 并且生产者和消费者之间相互依赖 , 互为条件.
- 对于生产者 , 没有生产产品之前 , 要通知消费者等待 . 而生产了产品之后 , 又需要马上通知消费者消费
- 对于消费者 , 在消费之后 , 要通知生产者已经结束消费 , 需要生产新的产品以供消费.
- 产者消费者问题中 , 仅有synchronized是不够的
- synchronized 可阻止并发更新同一个共享资源 , 实现了同步
- synchronized 不能用来实现不同线程之间的消息传递 (通信)
-
解决方式
-
管程法
并发协作模型 “ 生产者 / 消费者模式 ” —->管程法
生产者 : 负责生产数据的模块 (可能是方法 , 对象 , 线程 , 进程) ;
消费者 : 负责处理数据的模块 (可能是方法 , 对象 , 线程 , 进程) ;
缓冲区 : 消费者不能直接使用生产者的数据 , 他们之间有个 “ 缓冲区
生产者将生产好的数据放入缓冲区 , 消费者从缓冲区拿出数据
-
//测试生产者消费者模型:管程法
public class Demo05 {
public static void main(String[] args) {
Syncontainer syContainer = new Syncontainer();
new Productor(syContainer).start();
new Consumer(syContainer).start();
}
}
//生产者
class Productor extends Thread{
Syncontainer syContainer;
public Productor(Syncontainer syContainer) {
this.syContainer = syContainer;
}
@Override
public void run() {
super.run();
for (int i = 1; i < 100; i++) {
syContainer.push(new Product(i));
System.out.println("生产了--->" + i);
}
}
}
//消费者
class Consumer extends Thread{
Syncontainer syContainer;
public Consumer(Syncontainer syContainer){
this.syContainer=syContainer;
}
@Override
public void run() {
super.run();
for (int i = 1; i < 100; i++) {
Product pop = syContainer.pop();
System.out.println("消费了"+pop.count);
}
}
}
//产品
class Product {
//数量
int count;
public Product(int id) {
this.count = id;
}
}
//缓冲区、
class Syncontainer{
//需要一个容器
Product[] products = new Product[10];
//容器计数器
int count = 0;
//生产者放入产品
public synchronized void push(Product product){
//如果容器满了,需等待消费者消费
if (count == products.length){
//通知消费者消费,生产等待
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
//如果容器没有满,需继续生产产品
products[count] = product;
count++;
//通知消费者消费,唤醒消费者
this.notifyAll();
}
}
//消费者消费产品
public synchronized Product pop() {
if (count == 0) {
//通知生产者生产,消费者等待
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//可以消费
count--;
Product product = products[count];
this.notifyAll();
return product;
}
}
-
信号灯法:
//测试生产者消费者模型:信号灯法
public class Demo06 {
public static void main(String[] args) {
Product product = new Product();
new Producer(product).start();
new Consumer(product).start();
}
}
//生产者
class Producer extends Thread {
Product product;
public Producer(Product product){
this.product = product;
}
@Override
public void run() {
for (int i = 0; i < 20; i++) {
if (i%2==0){
try {
this.product.produce("电视");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
//消费者
class Consumer extends Thread{
Product product;
public Consumer(Product product){
this.product = product;
}
@Override
public void run() {
for (int i = 0; i < 20; i++) {
try {
product.consume();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
//产品
class Product{
String name;
boolean flag = true;
public synchronized void produce(String name) throws InterruptedException {
if (!flag){
this.wait(); //生产者等待
}
System.out.println("生产产品");
//通知消费者消费
this.notifyAll();//通知唤醒
this.name = name;
this.flag = !this.flag;
}
public synchronized void consume() throws InterruptedException {
if (flag){
this.wait();
}
System.out.println("正在消费"+name);
//通知生产者生产
this.notifyAll();
this.flag = !this.flag;
}
}

浙公网安备 33010602011771号