/**
*线程协作
*线程之间需要进行通信,通信有数据共享(1、文件共享;2、网络共享;3、变量共享)和线程协作两种方式。
*线程协作指不同线程驱动的任务相互依赖,依赖一般就是对共享资源的依赖。(有共享就有竞争,有竞争就会有线程安全问题(即并发),解决并发问题就用线程同步)。
?*
*应用场景:生产者和消费者问题
*假如仓库中只能存放一件商品,生产者将生产出来的产品放入仓库,消费者将仓库中产品取走消费。
*如果仓库中没有产品,则生产者将产品放入仓库,否则停止生产并等待,直到仓库中的产品被消费者取走为止。
*如果仓库中放有产品,则消费者可以将产品取走消费,否则停止消费并等待,直到仓库中再次放入产品为止。
?*
*场景分析:这是一个线程同步问题,生产者和消费者共享同一个资源,并且生产者和消费者之间相互依赖,互为条件。
*对于生产者,没有生产产品之前,要通知消费者等待。而生产了产品之后,又需要马上通知消费者消费。
*对于消费者,在消费之后,要通知生产者已经结束消费,需要生产新的产品以供消费。
*在生产者消费者问题中,没生产出产品之前,消费者是不能消费的,反之,消费者没消费完之前,生产者是不能生产的。
*这就需要锁来实现线程之间的同步。仅有同步还不行,还要实现线程之间的消息传递,即通信。
?*
* Java提供了解决线程之间通信问题的方法:
*方法名 作用
?* wait () 表示线程一直等待,直到其他线程通知,与sleep不同会释放锁
?* wait (long timeOut) 指定等待的毫秒数
?* notify () 唤醒一个处于等待状态的线程
?* notifyAll() 唤醒同一个对象所有的调用wait()方法的线程,优先级高的优先调度
*注意:均是Object的方法,均只能在同步方法或者同步代码块中使用,否则会抛出异常IIIegalMonitorStageException。
?*
*解决线程之间通信的方式:管程法和信号灯法。本例为管程法。
?*
?*/
public class MyWait {
????public static void main(String[] args) {
????????SynContainer container = new SynContainer();
????????new Productor(container).start();
????????new Consumer(container).start();
????}
}
//产品
class Chicken {
????int id;
????public Chicken (int id) {
????????this.id = id;
????}
}
//生产者
class Productor extends Thread {
????SynContainer synContainer;
????public Productor(SynContainer synContainer) {
????????this.synContainer = synContainer;
????}
????@Override
????public void run() {
????????for (int i = 0; i < 20; i++) {
????????????synContainer.pushTo(new Chicken(i));
????????}
????}
}
//消费者
class Consumer extends Thread {
????SynContainer synContainer;
????public Consumer(SynContainer synContainer) {
????????this.synContainer = synContainer;
????}
????@Override
????public void run() {
????????for (int i = 0; i < 20; i++) {
????????????synContainer.popTo();
????????}
????}
}
//容器
class SynContainer {
//定义一个大小为10的容器
????Chicken[] chickens = new Chicken[10];
//容器计数器
????int count;
//生产者生产产品方法
????public synchronized void pushTo(Chicken chicken) {
//如果容器满了,就停止生产
????????if (chickens.length == count) {
????????????try {
????????????????this.wait();
????????????} catch (InterruptedException e) {
????????????????e.printStackTrace();
????????????}
????????}
//如果容器没满,就往容器中放入产品
????????chickens[count] = chicken;
System.out.println("生产了" + chicken.id + "个鸡腿");
????????count ++;
//通知消费者消费
????????this.notifyAll();
????}
//消费者消费产品方法
????public synchronized Chicken popTo() {
//如果容器中没有产品了,就停止消费
????????if (count == 0) {
????????????try {
????????????????this.wait();
????????????} catch (InterruptedException e) {
????????????????e.printStackTrace();
????????????}
????????}
//如果容器有产品,就可以消费
????????count --;
????????Chicken chicken = chickens[count];
System.out.println("消费了第" + chicken.id + "个鸡退");
//只要消费了,就通知生产者生产
????????this.notifyAll();
????????return chicken;
????}
}