生产者消费者模式

1,生产者只在仓库未满时进行生产,仓库满时生产者进程被阻塞。

2,消费之只在仓库非空时进行消费,仓库为空时消费者进程被阻塞。

生产者消费者问题都是通过锁的竞争进行资源的消耗或生产。

方法一:synchronized,wait,notify

资源

public class Resource {
    //当前资源的数量
    int number = 0;
    //当前资源的上限
    int size = 10;
    //控制执行的标识
    boolean flag = true;

    //生产资源
    public synchronized void produce() {
        //如果资源满了,就进入阻塞状态
        //jdk里推荐用while,因为有可能出现虚假唤醒,所以再次确认
        while (number == size) {
            try {
                System.out.println(Thread.currentThread().getName() + "\t" + "进入等待");
                //线程进入阻塞状态,并释放锁
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        number++;
        System.out.println(Thread.currentThread().getName() + "\t" + "生产资源" + number);
        //唤醒其他正在等待的线程
        this.notify();
    }

    //消费资源
    public synchronized void consume() {
        //如果num为0,没有资源了,需要等待
        //这里jdk源码里推荐用while,因为有可能虚假唤醒,所以要再次确认
        while (number == 0) {
            try {
                System.out.println(Thread.currentThread().getName() + "\t" + "进入等待");
                //线程等待,并释放锁
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println(Thread.currentThread().getName() + "\t" + "消费资源" + number);
        number--;
        //唤醒其他正在等待的线程
        this.notify();
    }

    //停止执行
    public void stop() {
        this.flag = false;
    }
}

生产者

public class Producer implements Runnable {
    private Resource resource;
    public Producer(Resource resource){
        this.resource=resource;
    }

    @Override
    public void run() {
        while (resource.flag){
            resource.produce();
        }
        System.out.println(Thread.currentThread().getName()+"\t"+"生产者停止线程");
    }
}

消费者

public class Consumer implements Runnable {
    private Resource resource;
    public Consumer(Resource resource){
        this.resource=resource;
    }

    @Override
    public void run() {
        while (resource.flag){
            resource.consume();
        }
        System.out.println(Thread.currentThread().getName()+"\t"+"消费者停止线程");
    }
}

测试代码

public class TestProducerAndConsumer {
    public static void main(String[] args) {
        Resource resource = new Resource();
        Thread producer=new Thread(new Producer(resource),"producer");
        Thread consumer=new Thread(new Consumer(resource),"consumer");
        producer.start();
        consumer.start();

        try {
            TimeUnit.SECONDS.sleep(5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("停止线程");
        resource.flag=false;
    }
}

方法二:lock,condition,await,singal

资源

public class Resource {
    //当前资源的数量
    int number = 0;
    //当前资源的上限
    int size = 10;
    //控制执行的标识
    boolean flag = true;
    //创建所对象
    Lock lock = new ReentrantLock();
    //创建锁的条件、情况
    Condition condition = lock.newCondition();

    //生产资源
    public void produce() {
        //开启锁
        lock.lock();
        try {
            //当资源满时,需要等待
            //jdk源码里推荐使用while,因为有可能出现虚假唤醒,所以再次确认
            while (number == size) {
                System.out.println(Thread.currentThread().getName() + "\t" + "进入等待");
                try {
                    //线程等待,释放锁
                    condition.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            number++;
            System.out.println(Thread.currentThread().getName() + "\t" + "生产资源" + number);
            //唤醒其他线程
            condition.signal();
        } finally {
            lock.unlock();
        }
    }

    //消费资源
    public void consume() {
        //开启锁
        lock.lock();
        try {
            //如果number为0,没有资源了,需要等待
            //jdk源码里推荐使用while,因为有可能出现虚假唤醒,所以再次确认
            while (number == 0) {
                System.out.println(Thread.currentThread().getName() + "\t" + "进入等待");
                try {
                    //线程等待,释放锁
                    condition.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println(Thread.currentThread().getName() + "\t" + "消费资源" + number);
            number--;
            //唤醒其他线程
            condition.signal();
        } finally {
            //释放锁
            lock.unlock();
        }
    }

    public void stop() {
        this.flag = false;
    }
}

生产者、消费者和测试代码都和上面一样。

方法三:BlockingQueue

资源

public class Resource {
    AtomicInteger atomicInteger=new AtomicInteger();
    boolean flag=true;
    BlockingQueue blockingQueue=null;
    public Resource(BlockingQueue blockingQueue){
        this.blockingQueue=blockingQueue;
    }

    public void produce(){
        try {
            int number = atomicInteger.incrementAndGet();
            boolean result = blockingQueue.offer(number, 2L, TimeUnit.SECONDS);
            if(result){
                System.out.println(Thread.currentThread().getName()+"\t"+"生产资源成功"+number);
            }else{
                System.out.println(Thread.currentThread().getName()+"\t"+"生产资源失败"+number);
            }
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public void consume(){
        try {
            Integer number =(Integer) blockingQueue.poll(2L, TimeUnit.SECONDS);
            if(number==null){
                flag=false;
                System.out.println(Thread.currentThread().getName()+"\t"+"超过2秒钟消费资源,线程停止");
                return;
            }
            System.out.println(Thread.currentThread().getName()+"\t"+"消费资源"+number);
            //atomicInteger.getAndDecrement();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public void stop(){
        this.flag=false;
    }
}

生产者

public class Producer implements Runnable {
    Resource resource=null;
    public Producer(Resource resource){
        this.resource=resource;
    }

    @Override
    public void run() {
        while (resource.flag){
            resource.produce();
        }
        System.out.println(Thread.currentThread().getName()+"\t"+"生产线程停止了");
    }
}

消费者

public class Consumer implements Runnable {
    Resource resource=null;
    public Consumer(Resource resource){
        this.resource=resource;
    }

    @Override
    public void run() {
        while (resource.flag){
            resource.consume();
        }
        System.out.println(Thread.currentThread().getName()+"\t"+"消费线程停止了");
    }
}

测试代码

public class TestProducerAndConsumer {
    public static void main(String[] args) {
        BlockingQueue<Integer> blockingQueue=new ArrayBlockingQueue<>(10);
        Resource resource=new Resource(blockingQueue);
        Thread producer = new Thread(new Producer(resource), "producer");
        Thread consumer = new Thread(new Consumer(resource), "consumer");
        producer.start();
        consumer.start();
        try {
            TimeUnit.SECONDS.sleep(30);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("停止线程");
        resource.flag=false;
    }
}