生产者消费者模式
解决方式1:生产者/消费者模式–>管程法
- 生产者:负责生产数据的模块(这里的模块可能是:方法,对象,线程,进程)
- 消费者:负责处理数据的模块(这里的模块可能是:方法,对象,线程,进程)
- 缓冲区:消费者不能直接使用生产者的数据,它们之间有个“缓冲区”,生产者将生产好的数据放入“缓冲区”,消费者从“缓冲区”拿要处理的数据。
解决方式2:生产者消费者模式–>信号灯法
借助标志位来表明生产者是否可以生产,消费者是否可以消费。
方法
java提供了3个方法解决线程之间的通信问题
均是Object类的方法,都只能在同步方法或同步块中使用,否则会抛出异常。
管程法
- 生产者:多线程,当缓冲区满的时候等待。
- 消费者:多线程,当缓冲区空的时候等待。
- 缓冲区:并发容器(例子比较简单自己手写的)。
package ThreadClass;
/**
* 测试管程法
* @author 王星宇
* @date 2020年2月18日
*/
public class Cotest {
public static void main(String[] args) {
Container con = new Container();
new Producer(con).start();
new Consumer(con).start();
}
}
//生产者
class Producer extends Thread{
Container con;
public Producer(Container con) {
this.con = con;
}
public void run() {
for(int i = 1;i < 100;i++) {
System.out.println("生产第" + i + "个蛋糕");
con.push(new cake(i));
}
}
}
//消费者
class Consumer extends Thread{
Container con;
public Consumer(Container con) {
this.con = con;
}
public void run() {
for(int i = 1 ;i < 100;i++) {
cake temp = con.pop();
System.out.println("消费第" + temp.id + "个蛋糕");
}
}
}
//缓冲区
class Container{
cake[] cc = new cake[10];
int count = 0;
//生产
public synchronized void push(cake cc) {
//如果容器满了,则线程阻塞,等待消费者唤醒
if(count == 10) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.cc[count++] = cc;
//生产者生产了,通知消费者消费
this.notifyAll();//因为只有一个线程在阻塞,notify和notifyAll一样
}
//消费
public synchronized cake pop() {
//如果容器为空,则线程阻塞,等待生产者唤醒
if(count == 0) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
cake temp = this.cc[--count];
this.notifyAll();
return temp;
}
}
//数据
class cake{
int id;
public cake(int id) {this.id = id;}
}
信号灯法
借助标志位。
package ThreadClass;
/**
* 测试信号灯法
* @author 王星宇
* @date 2020年2月18日
*/
public class Contest {
public static void main(String[] args) {
TV tv = new TV();
new player(tv).start();
new watcher(tv).start();
}
}
//生产者 演员
class player extends Thread{
TV tv;
public player(TV tv) {
this.tv = tv;
}
public void run() {
for(int i = 0;i < 10;i++) {
tv.play("爱就一个字,我只说" + (i + 1) + "次");
}
}
}
//消费者 观众
class watcher extends Thread{
TV tv;
public watcher(TV tv) {
this.tv = tv;
}
public void run() {
for(int i = 0;i < 10;i++) {
tv.watch();
}
}
}
//同一个资源 tv
class TV{
String voice;
//信号灯
//T表示演员表演,观众等待
//F表示观众观看,演员等待
boolean flag = true;
//表演
public synchronized void play(String voice) {
//如果信号灯灭,等待
if(!flag) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("表演了:" + voice);
this.voice = voice;
//通知观众观看
this.notifyAll();
//改变信号灯
this.flag = false;
}
//观看
public synchronized void watch() {
//如果信号灯亮,等待
if(flag) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("听到了:" + voice);
//通知演员表演
this.notifyAll();
//改变信号灯
this.flag = true;
}
}