Java线程协作之生产者与消费者模型

概述

前面我们学习了多线程的一些基本使用,似乎已经满足了我们大部分的多线程需求,例如最常见的多线程爬虫,但这些也就只是最常用的。如果我们在业务层使用多线程技术,则需要考虑并发协作。
即多个线程进行通讯,所以这里尝试编写了一个生产者与消费者模型

思路

我们现在尝试去抽象化一下。
现有三个类:消费者、生产者、控制层。

生产者:当货品 >10 的时候生产者停止生产。当货品 <1 的时候提醒生产者生产。
消费者:当货品 >0 的时候消费者进行购买。当货品 <1 的时候消费者停止购买。

所以,我们需要有一层进行控制。这里又要学会两个函数:
Thread.wait() 将线程进入睡眠状态。 Thread.notfyAll() 线程唤醒Thread.notifyAll()唤醒全部函数。

思路很简单。我们只需要创建两个线程,当不满足以上条件之时就将线程睡眠,反之唤醒所有线程。
值得一说的是,下图我们使用的CopyOnWriteArraylist()是不会出现线程安全问题,因为它的底层是自带锁的。

代码

import java.util.concurrent.CopyOnWriteArrayList;

public class WaitDemo {

    public static void main(String[] args) {
        Container container = new Container();
        new Producer(container).start();
        new Consumer(container).start();
    }

}

//生产者
class Producer extends Thread {
    Container container;

    public Producer(Container container) {
        this.container = container;
    }

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            try {
                Thread.sleep(500);
                container.push(i);
                System.out.println("生产了一个编号为" + i + "的物品。");

            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

//消费者
class Consumer extends Thread {
    Container container;

    public Consumer(Container container) {
        this.container = container;
    }

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            try {
                System.out.println("消费了编号为" + container.pop() + "的物品。");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

class Container {
    private CopyOnWriteArrayList<Integer> list = new CopyOnWriteArrayList<>();

    public synchronized void push(Integer integer) throws InterruptedException {
        if (list.size() == 10) {
            this.wait();
        }
        list.add(integer);
        this.notifyAll();
    }

    public synchronized int pop() throws InterruptedException {
        if (list.size() == 0) {
            this.wait();
        }
        Integer integer = list.get(list.size() - 1);
        list.remove(list.size() - 1);
        this.notifyAll();
        return integer;

    }

}