生产者消费者
一,线程通信问题
应用场景:生产者和消费者问题
假设仓库中只能存放一件产品,生产者将生产出来的产品放入仓库,消费者将仓库中产品取走消费
如果仓库中没有产品,则生产者将产品放入仓库,否则停止生产并等待,直到仓库中的产品被消费者取走为止
如果仓库中放有产品,则消费者可以将产品取走消费,否则停止消费并等待,直到仓库中再次放入产品为止
生产者:
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(); } } }
心有所想,必有回响