概述
前面我们学习了多线程的一些基本使用,似乎已经满足了我们大部分的多线程需求,例如最常见的多线程爬虫,但这些也就只是最常用的。如果我们在业务层使用多线程技术,则需要考虑并发协作。
即多个线程进行通讯,所以这里尝试编写了一个生产者与消费者模型。
思路
我们现在尝试去抽象化一下。
现有三个类:消费者、生产者、控制层。
生产者:当货品 >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;
}
}