线程协作:生产者消费者模式:这个模式不是类与类的模式,
* 是处理线程协作的模型,处理线程通信的问题。
* 生产者与消费者共享同一资源,并且生产者和消费者之间互相依赖,
* 互为条件:1.对于生产者,没有生产产品之前,要通知消费者等待,
* 生产了之后通知消费者消费;
* 2.对于消费者,在消费之后,要通知生产者已经消费完了,
* 需要继续生产新产品给消费者;
* 在生产者消费者问题中,仅有syncharonized是不够的:
* 1.syncharonized可阻止并发更新同一个共享资源,实现了同步;
* 2.syncharonized不能来实现不同线程之间的消息传递(通信)
怎么实现通信?
两种通信方法:1.管程法:生产者只负责生产数据模块,消费者只负责
* 处理数据模块,两个模块之间有个缓冲区,生产者将生产好的数据放
* 入缓冲区,消费者从缓冲区拿数据。
* 2.信号灯法,原理和红绿灯一样,借助标志位
* Java提供了4个方法解决线程之间的通信问题:
* 1.wait():表示线程一直等待,直到其他线程通知,与sleep不同,会释放锁。
* 2.wait(long timeout):指定等待毫秒数
* 3.notify();唤醒一个处于等待的线程
* 4.notifyAll():唤醒同一个对象上所以调用wait方法的线程,优先级高的线程
* 优先调度
* 注意:这4个方法都是java.lang.Object类的方法;都只能在同步方法会同步块
* 中使用,否则会抛异常
第一种方式:管程法:模拟生产数据
//生产者
class Productor extends Thread{
SynContainer container;
public Productor(SynContainer container) {
this.container = container;
}
@Override
public void run() {
for (int i = 0; i <100 ; i++) {
System.out.println("生产第"+i+"个");
container.push(new Datas(i));
}
}
}
//消费者
class Consumer extends Thread{
SynContainer container;
public Consumer(SynContainer container) {
this.container = container;
}
@Override
public void run() {
for (int i = 0; i <100 ; i++) {
System.out.println("消费第"+container.pop().id+"个");
}
}
}
//缓冲区
class SynContainer{
Datas[] datas = new Datas[10];//存储容器
int count = 0;//计数器
/*
存储 生产
容器有空间可以生产
*/
public synchronized void push(Datas data){
if(count == datas.length){//没有空间了
try {
this.wait();//线程阻塞 消费者通知生产者停止生产
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//有空间了 可以生产
datas[count] = data;
count ++;
this.notifyAll();//继续生产
}
/*
获取 消费
有数据就可以消费 没数据就要等待
*/
public synchronized Datas pop(){
if(count==0){//没有数据
try {
this.wait();//线程阻塞 生产者通知消费等待
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//有数据可以消费
count--;
Datas data = datas[count];
this.notifyAll();//继续消费
return data;
}
}
//数据
class Datas{
int id;
public Datas(int id) {
this.id = id;
}
}
信号灯法:模拟电视
//生产者 演员
class Player extends Thread{
Tv tv;
public Player(Tv tv) {
this.tv = tv;
}
@Override
public void run() {
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) {
this.tv = tv;
}
@Override
public void run() {
for (int i = 0; i <20 ; i++) {
this.tv.watch();
}
}
}
//同一资源
class Tv{
String voice;
/*
信号灯
flag为真,表示演员表演 观众等待
flag为假,表示观众观看 演员等待
*/
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 = !this.flag;//换信号灯
}
public synchronized void watch(){
if(flag){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("看到了"+voice);
this.notifyAll();
this.flag = !this.flag;
}
}
结果可以看到,表演了什么就看什么。