一、生产者消费者模式
1、解决的是线程通信的问题。(解耦、效率高)
2、管程法:生产者和消费者之间设置一个缓冲区,生产者和消费者之间的耦合度较低,维护简单。(解耦)
3、红绿灯法
二、解决线程通信问题的三个方法
1、final void wait()
:表示线程一直等待,直到其他线程通知,与sleep()
不同,会释放锁。
2、final void wait(long timeout)
:指定等待的毫秒数。
3、final void notify()
:唤醒一个处于等待状态的线程.
4、final void notifiAll()
:唤醒同一个对象上的所调用wait()方法的线程,由此按级别高的线程优先调度。
以上的方法都只能在同步方法或者同步块中使用,否则会抛出异常
三、管程法
下面数据缓冲区大小为10进行生产者消费者模式
/**
* 生产者消费者模式一:管程
* @author 鹏鹏
*
*/
public class CorperationTest {
public static void main(String[] args) {
SynContainer synContainer = new SynContainer();
new Thread(new Productor(synContainer)).start();
new Thread(new Customer1(synContainer)).start();
}
}
//生产者
class Productor implements Runnable{
SynContainer syncontainer;
public Productor(SynContainer syncontainer) {
this.syncontainer = syncontainer;
}
@Override
public void run() {
for(int i=0;i<100;i++)
{
System.out.println("生产-->"+i+"个数据");
syncontainer.push(new Data(i));
}
}
}
//消费者
class Customer1 implements Runnable{
SynContainer syncontainer;
public Customer1(SynContainer syncontainer) {
// TODO 自动生成的构造函数存根
this.syncontainer = syncontainer;
}
@Override
public void run() {
for(int i=0;i<100;i++)
{
System.out.println("消费-->"+syncontainer.pop().id+"个数据");
}
}
}
//缓冲区
class SynContainer {
Data[] data = new Data[10]; //缓冲区大小10个数据
int count = 0; //计数器
//存储,生产
public synchronized void push(Data data1) {
//何时生产,容器存在空间
//不能生茶,就等待
if(count == data.length) {
try {
this.wait(); //消费者通知生产就解除
} catch (InterruptedException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
//存在数据通知消费
data[count] = data1;
count++;
this.notifyAll();
}
//获取数据,消费
public synchronized Data pop() {
//看容器中是否存在数据,没有数据只能等待
if(count==0) {
try {
this.wait(); //此时线程阻塞,生产者通知消费就解除阻塞
} catch (InterruptedException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
//存在数据可以消费
count--;
Data data2 = data[count]; //获取最后一个数据
//存在空间唤醒对方生产
this.notifyAll();
return data2;
}
}
//数据
class Data{
int id;
public Data(int id) {
this.id = id;
}
}
四、红绿灯法
/**
* 生产者消费者模式信号灯法,借助标志位,举例关账收看节目
* @author 鹏鹏
*
*/
public class CorperationTestTrafficLights {
public static void main(String[] args) {
Tv tv = new Tv();
new Thread(new Actor(tv)).start();
new Thread(new Audience(tv)).start();
}
}
//生产者演员
class Actor implements Runnable{
Tv tv;
public Actor(Tv tv) {
this.tv = tv;
}
public void run() {
for(int i=0;i<20;i++) {
if(i%2==0) {
this.tv.play("西游记");
}else {
this.tv.play("广告");
}
}
}
}
//消费者观众
class Audience implements Runnable{
Tv tv;
public Audience(Tv tv) {
this.tv = tv;
}
public void run() {
tv.watch();
}
}
//同一份资源电视
class Tv{
String voice;
//信号灯True表示演员表演观众等待,false表示观众观看,演员等待
boolean flag = true;
//表演
public synchronized void play(String voice) {
//演员等待
if(!flag) {
try {
this.wait();
} catch (InterruptedException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
//演员表演
System.out.println("发出了了"+voice);
this.voice = voice;
this.notifyAll();
flag = !flag;
}
//观看
public synchronized void watch() {
//观众等待
if(flag) {
try {
this.wait();
} catch (InterruptedException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
//观众观看
System.out.println("听到了"+voice);
this.notifyAll();
flag = !flag;
}
}