生产者消费者

一,线程通信问题

应用场景:生产者和消费者问题

假设仓库中只能存放一件产品,生产者将生产出来的产品放入仓库,消费者将仓库中产品取走消费

如果仓库中没有产品,则生产者将产品放入仓库,否则停止生产并等待,直到仓库中的产品被消费者取走为止

如果仓库中放有产品,则消费者可以将产品取走消费,否则停止消费并等待,直到仓库中再次放入产品为止

生产者:

package producerconsumer.demo1;

/**
 * @Author zl
 * @Description
 * @Date 2021/12/20 19:52
 */
public class Producer implements Runnable {

    private Product product;

    public Producer() {
    }

    public Producer(Product product) {
        this.product = product;
    }

    @Override
    public void run() {

        for (int i = 0; i < 10; i++) {
            synchronized (product) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if (product.isFlag()) {
                    try {
                        product.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

                if (i % 2 == 0) {
                    product.setBrand("哇哈哈");
                    product.setName("矿泉水");
                } else {
                    product.setBrand("旺仔");
                    product.setName("小馒头");
                }
                System.out.println("生产者生产了:" + product.getBrand() + "-" + product.getName());
                product.setFlag(true);

                product.notify();
            }
        }


    }
}

 

消费者:

package producerconsumer.demo1;

/**
 * @Author zl
 * @Description
 * @Date 2021/12/20 19:52
 */
public class Consumer implements Runnable {
    private Product product;

    public Consumer() {
    }

    public Consumer(Product product) {
        this.product = product;
    }

    @Override
    public void run() {

        for (int i = 0; i < 10; i++) {
            synchronized (product) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if (!product.isFlag()) {
                    try {
                        product.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

                System.out.println("消费者消费了:" + product.getBrand() + "-" + product.getName());
                product.setFlag(false);
                product.notify();
            }
        }


    }
}

 

产品:

package producerconsumer.demo1;

/**
 * @Author zl
 * @Description
 * @Date 2021/12/20 19:52
 */
public class Product {
    private String name;

    private String brand;

    private boolean flag = false;

    public boolean isFlag() {
        return flag;
    }

    public void setFlag(boolean flag) {
        this.flag = flag;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getBrand() {
        return brand;
    }

    public void setBrand(String brand) {
        this.brand = brand;
    }
}

 

测试:

package producerconsumer.demo1;

/**
 * @Author zl
 * @Description
 * @Date 2021/12/20 19:53
 */
public class Test {
    public static void main(String[] args) {
        Product product = new Product();
        Runnable t1 = new Producer(product);
        Runnable t2 = new Consumer(product);
        Thread producer = new Thread(t1);
        Thread consumer = new Thread(t2);
        producer.start();
        consumer.start();

    }
}

 二,Loc锁情况下的线程通信

Condition是在Java 1.5中才出现的,它用来替代传统的Object的wait()、notify()实现线程间的协作,相比使用Object的wait()、notify(),使用Condition的await()、signal()这种方式实现线程间协作更加安全和高效。 

 

它的更强大的地方在于:能够更加精细的控制多线程的休眠与唤醒。对于同一个锁,我们可以创建多个Condition,在不同的情况下使用不同的Condition 

一个Condition包含一个等待队列。一个Lock可以产生多个Condition,所以可以有多个等待队列。

Object的监视器模型上,一个对象拥有一个同步队列和等待队列,Lock(同步器)拥有一个同步队列和多个等待队列。 

Object中的wait(),notify(),notifyAll()方法是和"同步锁"(synchronized关键字)捆绑使用的;而Condition是需要与"互斥锁"/"共享锁"捆绑使用的。 

调用Condition的await()、signal()、signalAll()方法,都必须在lock保护之内,就是说必须在lock.lock()和lock.unlock之间才可以使用 

  • Conditon中的await()对应Object的wait();
    • Condition中的signal()对应Object的notify();
  • Condition中的signalAll()对应Object的notifyAll()。 
package thread.producerconsumer.demo4;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @Author zl
 * @Description
 * @Date 2021/12/20 19:52
 */
public class Product {
    private String name;

    private String brand;

    private Lock lock = new ReentrantLock();

    private Condition producerCondition = lock.newCondition();

    private Condition consumerCondition = lock.newCondition();

    private boolean flag = false;

    public boolean isFlag() {
        return flag;
    }

    public void setFlag(boolean flag) {
        this.flag = flag;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void set(String brand, String name) {
        lock.lock();
        try {
            if (isFlag()){
                producerCondition.await();
            }
            this.setBrand(brand);
            this.setName(name);
            System.out.println(Thread.currentThread().getName()+"生产者生产了:" + getBrand() + "-" + getName());
            flag=true;
            consumerCondition.signal();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }

    }

    public String getBrand() {
        return brand;
    }

    public void setBrand(String brand) {
        this.brand = brand;
    }

    public void get(){
        lock.lock();
        try {
            if (!isFlag()){
                consumerCondition.await();
            }

            System.out.println(Thread.currentThread().getName()+"消费者消费了:" + getBrand() + "-" + getName());
            flag=false;
            producerCondition.signal();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
}

 

posted @ 2022-11-01 22:04  风子磊  阅读(93)  评论(0编辑  收藏  举报