多线程 - 生产者与消费者

经典面试题

数据容器:封装生产、消费所需的数据。
生产者:从容器中填装东西,东西生产好了,及时通知消费者。
消费者:从容器取数据,东西取完了,及时通知生存者生产。

分析

没有任何实战价值,但是面试的时候会问。

本文主要是想介绍 Thread 相关的函数,一般不会用到这么底层的代码。

推荐方案:使用读写锁,或者直接使用阻塞队列

Wait、Notify、NotifyAll

主要就介绍这三个方法,本案例也就用到他们:


如果对象调用了wait方法就会使持有该对象的线程把该对象的控制权交出去,然后处于等待状态。
对象叫Container,A线程不再使用Container,那就等待


如果对象调用了notify方法就会通知某个正在等待这个对象的控制权的线程可以继续运行。
A线程等待了,但是得通知某一个等待的线程来使用Container


如果对象调用了notifyAll方法就会通知所有等待这个对象控制权的线程继续运行。
通知所有在等待的线程

其它方法也顺带提一下:

  • join():加入其它线程,并且等待join的线程执行完成,再执行自己的
  • join(millis):等待被join的线程的时间最长为millis毫秒。如果在millis毫秒内被join的线程还没有执行结束,则不再等待。
  • yield():给优先级高或者相同的线程让步
  • setDaemon():将普通线程变为后台线程,直接使用方法即可。
数据容器:
public class Container {
    private int count = 0;
    private Vector<String> vector = new Vector<>();
    private static final Container CONTAINER = new Container();

    private Container() {
    }

    public static Container getContainer() {
        return CONTAINER;
    }

    public synchronized void put() {
        //通知其它线程
        this.notifyAll();
        String name = Thread.currentThread().getName();
        while (vector.size() > 10) {
            System.out.println("container is filled...");
            try {
                //如果集合内容超过10等待
                this.wait();
                System.out.println("###" + name + "等待");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        count++;
        vector.add("Milk:" + count);
        System.out.println("###" + name + "生产一个产品");
    }

    public synchronized String get() {
        //通知其它线程
        this.notifyAll();
        String name = Thread.currentThread().getName();
        String milk = null;
        while (vector.size() <= 0) {
            System.out.println("container is empty...");
            try {
                //如果集合内容为0等待
                this.wait();
                System.out.println("---" + name + "等待");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        milk = vector.get(0);
        vector.remove(0);
        System.out.println("---" + name + "消费一个产品");
            return milk;
    }
}
生产者
public class Fatory extends Thread {
    private Container container = Container.getContainer();
    private boolean threadStop = false;

    public Fatory(String name) {
        super(name);
        this.start();
    }

    @Override
    public void run(){
        while (!threadStop) {
            try {
                container.put();
                Thread.sleep(300);
            } catch (InterruptedException e) {
                Thread.interrupted();
            }
        }
    }

    public void threadStop(){
        this.threadStop=true;
    }
}
消费者:
public class Shop extends Thread {
    private Container container = Container.getContainer();
    private boolean threadStop = false;

    public Shop(String name) {
        super(name);
        this.start();
    }

    @Override
    public void run() {
        while (!threadStop) {
            try {
                container.get();
                Thread.sleep(800);
            } catch (InterruptedException e) {
                Thread.interrupted();
            }
        }
    }

    public void threadStop() {
        this.threadStop = true;
    }
}

测试方法:
public class Test {
    public static void main(String[] args) {
        new Fatory("factoryA");
        new Fatory("factoryB");
        new Shop("shopA");
        new Shop("shopB");
        new Shop("shopC");
    }
}

posted on 2016-11-14 01:21  疯狂的妞妞  阅读(149)  评论(0编辑  收藏  举报

导航