-
生产者和消费者问题
- 共享同一个资源,需要线程同步: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 {// 容器大小为10Chicken[] 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();}
}