1.生产者与消费者问题
解决方式1:(管道法)生产者将生产好的数据放入“缓冲区”,消费者从“缓冲区”拿走要处理的数据。
解决方式2:(信号灯法)
方法名 | 作用 |
final void wait() | 表示线程一直等待,直到其他线程通知,与sleep不同,会释放锁 |
final void wait(long tiimeout) | 指定等待的毫秒数 |
final void notify() | 唤醒一个处于等待状态的线程 |
final void notifyAll() | 唤醒同一个对象上所有调用wait()方法的线程,优先级别高的线程优先调度 |
2.代码实现
1.管道法
package cn.zwl.cooperation;
/**
*
* 生产者消费者的实现方式一:管道法
* @author dell
*角色1:生产者
*角色2:消费者
*角色3:缓冲区
*角色4:馒头
*
*
*
*/
class Producter extends Thread{
SynContainer container;
public Producter(SynContainer container) {
super();
this.container = container;
}
@Override
public void run() {
// TODO Auto-generated method stub
super.run();
for (int i = 0; i < 100; i++) {
System.out.println("生产第"+i+"个馒头");
container.push(new SteamedBun(i));
}
}
}
class Comsumer extends Thread{
SynContainer container;
public Comsumer(SynContainer container) {
super();
this.container = container;
}
@Override
public void run() {
// TODO Auto-generated method stub
super.run();
for (int i = 0; i < 100; i++) {
System.out.println("消费第"+container.pop().id+"个馒头");
}
}
}
class SynContainer{
SteamedBun[] buns=new SteamedBun[10];
int count=0;//计数器
//存储 生产
public synchronized void push(SteamedBun bun) {
//何时生产,容器存在空间
if(count==buns.length) {
try {
this.wait();//线程阻塞,消费者通知生产解除
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
buns[count]=bun;
count++;
this.notifyAll();//存在数据可以消费
}
//获取 消费
public synchronized SteamedBun pop() {
//何时消费 容器中是否存在数据
if(count==0) {
try {
this.wait();//线程阻塞,生产者通知消费就可以解除
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//存在数据消费
count--;
SteamedBun bun=buns[count];
this.notifyAll();//存在空间可以唤醒生产
return bun;
}
}
class SteamedBun{
int id;
public SteamedBun(int id) {
super();
this.id = id;
}
}
public class CoTest1 {
public static void main(String[] args) {
SynContainer container=new SynContainer();
new Producter(container).start();
new Comsumer(container).start();
}
}
2.信号灯法
package cn.zwl.cooperation;
/**
*
*
* 信号灯法:借助标志位
* @author dell
*生产者 演员
*消费者 观众
*同一个资源 电视
*/
public class CoTest2 {
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) {
super();
this.tv = tv;
}
@Override
public void run() {
// TODO Auto-generated method stub
for (int i = 0; i < 20; i++) {
if (i%2==0) {
this.tv.play("火星情报局");
} else {
this.tv.play("太污了,喝瓶立白洗洗嘴");
}
}
}
}
class Watcher extends Thread{
Tv tv;
public Watcher(Tv tv) {
super();
this.tv = tv;
}
@Override
public void run() {
// TODO Auto-generated method stub
super.run();
for (int i = 0; i <20; i++) {
this.tv.watch();
}
}
}
class Tv{
String voice;
//信号灯:T表示演员表演 观众等待;F表示观众观看 演员等待
boolean flag=true;
//表演
public synchronized void play(String voice) {
// TODO Auto-generated method stub
//演员等待
if (!flag) {
try {
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//表演
System.out.println("表演了:"+voice);
this.voice=voice;
//表演完了,唤醒等待线程
this.notifyAll();
this.flag=!this.flag;
}
public synchronized void watch() {
// TODO Auto-generated method stub
//观众等待
if (flag) {
try {
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//观众观看
System.out.println("听到了:"+voice);
//看完了,唤醒等待的线程并切换标志
this.notifyAll();
this.flag=!this.flag;
}
}