生产者消费者模型
生产者 - 消费者模型( Producer-consumer problem) 是一个非常经典的多线程并发协作的模型,在分布式系统里非常常见
- 生产者: 生产商品放入缓冲区
- 缓冲区:存放商品的地方,容量有限
- 消费者: 消费缓冲区的商品
java 实现生产者消费者模型
wait notify notifyAll 方法
调用 wait() 和notify()的对象必须是 同一个 ,因为会被放入 同一个等待队列里面,比如在生产者1 线程里面调用Warehouse.wait()方法, 生产者1线程就被放入 Warehouse的等待队列当中,直到Warehouse调用 notify()或者notifyAll()方法,就是是让线程得到obj锁
- wait( ),notify( ),notifyAll( )都属于Object基础类,也就是每个对象都有wait( ),notify( ),notifyAll( ) 的功能
- 当需要调用以上的方法的时候,需要对竞争资源进行加锁
也可以用condition接口实现
wait() 看起来是1个函数,其实是3个
(JDK11.0)Causes the current thread to wait until it is awakened, typically by being notified or interrupted, or until a certain amount of real time has elapsed.
导致当前线程等待(waiting),直到被唤醒(notify 或notifyAll )或者打断,或者一段时间过去(time-waiting)
wait()
导致当前的线程等待,直到其他线程调用此对象的notify( ) 方法或 notifyAll( ) 方法
wait(long timeout)
Causes the current thread to wait until either another thread invokes the notify( ) method or the notifyAll( ) method for this object, or a specified amount of time has elapsed.
导致当前的线程等待,直到其他线程调用此对象的notify() 方法或 notifyAll() 方法,或者指定的时间过完。
void wait(long timeout, int nanos)
Causes the current thread to wait until another thread invokes the notify( ) method or the notifyAll( ) method for this object, or some other thread interrupts the current thread, or a certain amount of real time has elapsed.
导致当前的线程等待,直到其他线程调用此对象的notify( ) 方法或 notifyAll( ) 方法,或者其他线程打断了当前线程,或者指定的时间过完。
- wait 必须加锁(lock)或者放入同步代码(synchronized)块里面
- 当运行到wait()方法,会立刻释放竞争对象的执行权
notify()
- Wakes up a single thread that is waiting on this object’s monitor.
唤醒在此对象监视器上等待的单个线程(也就是最先进入等待队列的线程) - 只有在同步代码块执行完毕之后,才会唤醒线程
notifyAll()
-Wakes up all threads that are waiting on this object’s monitor.
唤醒在此对象监视器上等待的所有线程(也就是在等待队列里的所有线程)
- 只有在同步代码块执行完毕之后,才会唤醒线程
java 代码
** 生产者Producer**
public class Producer implements Runnable {
Lock lock = new ReentrantLock();//锁
ArrayList<String> warehouse;
int goods = 0;
Producer(ArrayList<String> warehouse) {
this.warehouse = warehouse;
}
@Override
public void run() {
while (true) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
synchronized (warehouse) {
while (warehouse.size() >= 10) {
System.out.println("仓库容量" + warehouse.size() + " 容量满了,生产者停止消费");
System.out.println();
try {
warehouse.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}//加锁的时候,自动释放warehouse 的执行权
}
String a = String.valueOf(goods);
warehouse.add(a);
String thread_name = Thread.currentThread().getName();
System.out.println(thread_name + " 生产了 " + goods);
goods++;
warehouse.notify(); // 唤起消费者
}
}
}
}
** 消费者Costomer**
public class Customer implements Runnable{
Lock lock = new ReentrantLock();//锁
ArrayList<String> warehouse;
int goods=0;
Customer(ArrayList<String> warehouse){
this.warehouse =warehouse;
}
@Override
public void run() {
while (true){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
synchronized (warehouse){
while (warehouse.size() == 0){
System.out.println("没有货物了 消费者停止消费");
System.out.println();
try {
warehouse.wait(); //加入仓库的等待队列
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}// 没有货物,直接挂起
String good_name =warehouse.get(0);
String thread_name =Thread.currentThread().getName();
warehouse.remove(0);
System.out.println(thread_name+" 消费了 "+good_name);
//消费第一个货物
warehouse.notify();//唤醒生产者
}
}
}
}
** 主函数: 缓冲区Warehouse 是一个arrylist 默认容量是10 **
public class Main {
public static void main(String[] args) {
ArrayList<String> warehouse =new ArrayList<>(10);//容量是10
Customer customer =new Customer(warehouse);
Producer producer =new Producer(warehouse);
Thread thread_P1 = new Thread(producer);
thread_P1.setName("生产者1");
Thread thread_P2 = new Thread(producer);
thread_P2.setName("生产者2");
Thread thread_C1 = new Thread(customer);
thread_C1.setName("消费者1");
Thread thread_C2 = new Thread(customer);
thread_C2.setName("消费者2");
thread_P1.start();
thread_C1.start();
thread_P2.start();
thread_C2.start();
}
}
运行结果(看来花钱总比赚钱容易呀)