前要:
生产者消费者模式是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。
1.什么是wait方法?什么是notify方法?
wait方法,字面意思是等待,所以是让线程进入阻塞状态的过程;notify,字面意思是通知,所以是让线程醒来的过程。对于生产者-消费者模式来说,这两者相辅相成,若一方等待,必定意味着另一方要唤醒,相互配合工作。
2.实现流程
(1)创建生产者线程
class Prodecer implements Runnable{
@Override
public void run() {
}
}
(2)创建消费者线程
class Consumer implements Runnable{
@Override
public void run() {
}
}
(3)完善两个线程需要调控的资源,最终在主线程中启动这两个线程
3.具体代码实现产 这里我用比较简单的生产消费条件:即创建一个LinkedList,当其为空时,生产者进行生成,阻塞消费者;当其不为空时,消费者进行消费,阻塞生产者:
import java.util.LinkedList;
import java.util.List;
public class ThreadTest {
public static void main(String[] args) {
List list = new LinkedList<>();
Producor producor = new Producor(list);
Consumer consumer = new Consumer(list);
Thread pro = new Thread(producor);
Thread con = new Thread(consumer);
pro.start();
con.start();
}
}
class Producor implements Runnable{
List list;
public Producor(List list) {
this.list = list;
}
@Override
public void run() {
synchronized (list) {
while (true) {
if (list.size() > 0) {
try {
list.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Object o = new Object();
list.add(o);
System.out.println("Producer成功添加元素");
list.notify();
}
}
}
}
class Consumer implements Runnable{
List list;
public Consumer(List list) {
this.list = list;
}
@Override
public void run() {
synchronized (list) {
while (true) {
if (list.size() == 0) {
try {
list.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
list.remove(0);
System.out.println("已成功删除元素");
list.notify();
}
}
}
}
运行结果:
4.注意点
当多个线程操作同一个对象时,一般来说,我们需要保证线程安全,因此上述代码中运用了synchronized来控制每次只能有一个线程来控制对象,保证了其原子性。
5.其他两种实现生产者-消费者模式的方法
(1)使用Lock和await、signal
(2)使用阻塞队列BolckingQueue
这两种已经有许多大牛总结,可以自行查询