引入
这是一个线程同步问题,生产者和消费者共享一个资源,并且生产者相互依赖,互为条件。
- 对于生产者,没有生产产品之前,要通知消费者等待,生产了产品后,要通知消费者可以消费
- 对于消费者,在消费之后,要通知生产者自己结束了消费,可以生产产品了
-
synchronized
关键字可以阻止并发地更新同一个资源,可以实现同步,但是不能用来实现不同线程间的消息传递,也即是通信
wait | 让线程一直等待,直到其它线程通知,会释放锁,可以传递一个类型为long的参数,表示指定等待的毫秒数 |
---|---|
notify | 唤醒一个处于等待状态的线程 |
notifyAll | 唤醒同一个对象上所有调用wait方法的线程,优先级高的优先调度 |
上述方法均属于Object类的方法,只能在同步方法或者同步代码中使用,否则会抛出InterruptedException异常
并发协作模型“生产者/消费者模式” 管程法
- 生产者:负责生产数据的模块
- 消费者:负责处理数据的模块
- 缓冲区:消费者不能直接使用生产者的数据,要通过缓冲区将生产者的数据放入到缓冲区中,消费者再从缓冲区里面拿出数据
缓冲区
class Container<T>{
private LinkedList<T> list = new LinkedList<T>();
private final int MAX = 100;
private int count = 0;
//往缓冲区里面添加商品
public synchronized void put(T t){
while(list.size() == MAX){
try{
this.wait();;
}catch(InterruptedException e){
e.printStackTrace();
}
}
list.add(t);
System.out.println(Thread.currentThread().getName() + t);
this.notifyAll();
}
//从缓冲区里面消费商品
public synchronized void get() {
while (list.size() == 0){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
String t = (String) list.removeFirst();
System.out.println(Thread.currentThread().getName() + t);
this.notifyAll();
}
}
消费者
class Customer implements Runnable{
Container container;
public Customer(Container container) {
this.container = container;
}
@Override
public void run() {
while (true){
container.get();
}
}
}
生产者
class Productor implements Runnable{
Container container;
String name;
public Productor(Container container,String name) {
this.container = container;
this.name = name;
}
@Override
public void run() {
while (true){
container.put(name);
}
}
}
主函数
public class testThread{
public static void main(String[] args) {
Container<String> container = new Container();
new Thread(new Productor(container,"桃子"),"生产者1").start();
new Thread(new Customer(container),"消费者1").start();
new Thread(new Customer(container),"消费者2").start();
new Thread(new Productor(container,"雪梨"),"生产者2").start();
}
}
注意
在多生产者的情况下我们判断的时候要用
while
来做判断而不是
if
我们假设线程的调度是这样的,我们假设缓冲区最大容量为7,此时是已经达到最大容量,生产者线程都会被阻塞(此时生产者线程A已经经过
if
判断,在wait处等待,生产者线程B也通过了
if
判断,在wait处等待),当消费者通知生产者线程可以生产时(我们调用的是notifyAll方法),所有被阻塞的生产者线程都会被唤醒(A和B都会被唤醒),假如是生产者线程A获得了执行的机会,即获得了锁,而生产者线程B 继续在锁池中等待,
此时生产者线程B是醒着的
。假设生产者又把缓冲区生产满了,并且释放锁,生产者线程B获得锁,在这种情况下,B已经通过了
if
判断,即使缓冲区已经满了,但是B一样可以往里面添加数据,就会造成错误。假如我们用的是
while
。
版权声明:本文为weixin_43686867原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。