-
生产者和消费者问题
- 共享同一个资源,需要线程同步:synchronized
- 两者相互依赖,需要线程通信:wait()、notify()
-
wait()、notify()
-
解决线程通信
-
每个对象都有锁,因此是Object类的方法
-
只能在同步方法和同步代码块中使用,否则会抛出异常
IllegalMonitorStateException
-
wait()和notify()应该成对出现,不是说在一个方法里成对,而是分布在不同的方法里
-
为了防止有的线程太快,wait()让他停下来,等到慢的线程赶上了,再notify()快的线程,而且二者都有可能,所以要有两对
方法 注意 wait() 一直等待,直到其他线程唤醒,与sleep()不同,会释放锁 wait(long timeout) notify() 唤醒一个处于等待状态的线程 notifyAll() 唤醒所有,优先级高的优先调度
-
-
解决方式
- 管程法:新建一个缓冲区类,存放产品。生产者将生产的数据放入缓冲区,消费者从缓冲区拿数据
- 信号灯法:产品本身设置一个标志位flag
管程法
class Producer extends Thread{
SynContainer synContainer;
public void run() {
synContainer.produce(new Chicken(i));
}
}
class Consumer extends Thread{
SynContainer synContainer;
public void run() {
synContainer.consume();
}
}
// 产品
class Chicken {}
// 缓冲区(新建一个缓冲区类)
class SynContainer {
// 容器大小为10
Chicken[] chickens = new Chicken[10];
// 计数器
int count;
// 生产者放入产品
synchronized void produce(Chicken chicken) throws InterruptedException {
// 判断是否满了
if ((count == chickens.length)){
wait();
}
// 没满,放入产品
chickens[count++] = chicken;
System.out.println("生产了一只鸡" + chicken.id);
// 通知消费者消费
notifyAll();
}
// 消费者消费产品
synchronized void consume() throws InterruptedException {
// 判断缓冲区是否有值
if (count == 0){
wait();
}
// 有值,就消费
Chicken chicken = chickens[--count];
System.out.println("消费了" + chicken.id);
// 通知生产者生产
notifyAll();
}
}
信号灯法
class Actor extends Thread{
TV tv;
public void run() {
tv.perform("快乐大本营播放中");
}
}
class Audience extends Thread{
TV tv;
public void run() {
tv.watch();
}
}
// 产品,自身设置一个标志位
class TV{
String voice;
boolean flag = false;
// 表演
synchronized void perform(String voice) throws InterruptedException {
if (flag){
wait();
}
this.voice = voice;
System.out.println("演员表演了:"+voice);
flag = true;
notifyAll();
}
// 观看
synchronized void watch() throws InterruptedException {
if (!flag){
wait();
}
System.out.println("观众观看了:"+voice);
voice = null;
flag = false;
notifyAll();
}
}
标签:void,通信,flag,线程,voice,class,wait
From: https://www.cnblogs.com/xinyounuanyang/p/18685599