假设我们有一个商店,我们有产品库、消费者、生产者三类。
生产者让产品数量增加,消费者让产品数量减少,生产的产品添加到产品库里,消费者从产品库里拿走产品。
由此可知共享数据是产品,因此要考虑线程安全问题。
我们可以使用线程同步机制处理线程安全问题。
生产者生产产品时要判断产品库当前数量,如果已经达到最大量那么我们让消费者等待(wait/await);
消费者消费产品时也要判断产品库当前数量,若消费完了(即当前数量为0),此时不能继续消费了,消费者也需要等待(wait/await)。
一旦消费到头了,当生产者又生产了一个,消费者被唤醒(notify/signal)。
一旦生产到头了,当消费者又消费了一个,生产者被唤醒(notify/signal)。
下面是两种实现方式:
//wait和notify public class ProducerConsumerWithWaitNotify { //生产者线程 static class ProducerThread extends Thread{ private final Product product; public ProducerThread(Product product) { this.product = product; } public void run(){ //不断地生产产品 while(true){ try{ Thread.sleep(1000); } catch (InterruptedException e) { throw new RuntimeException(e); } //调用生产方法 product.add(); } } } //消费者线程 static class ConsumerThread extends Thread{ private final Product product; public ConsumerThread(Product product) { this.product = product; } public void run(){ //不断地消费产品 while(true){ try { Thread.sleep(1000); } catch (InterruptedException e) { throw new RuntimeException(e); } product.remove(); } } } //产品类 static class Product{ //当前产品数量 private int currentCount=0; //从产品库中取走产品 public synchronized void remove(){ if(currentCount>0){ currentCount--; System.out.println("消费者"+Thread.currentThread().getName()+"消费一件产品"+"当前线程池有"+currentCount+"个"); notifyAll();//通知生产者生产产品 }else{ try{ //如果没有产品,则消费者进入等待状态 wait(); System.out.println("消费者"+Thread.currentThread().getName()+"线程进入等待状态"); } catch (InterruptedException e) { throw new RuntimeException(e); } } } //向产品库中添加产品 public synchronized void add(){ int maxCount=10;//允许存放个数上限 if(currentCount<maxCount){ currentCount++; System.out.println(Thread.currentThread().getName()+"生产一件产品,当前产品库拥有"+currentCount+"个"); notifyAll();//通知等待的消费者 }else{ //如果满了 try{ wait();//生产者进入等待状态,并释放锁 System.out.println(Thread.currentThread().getName()+"线程进入等待状态"); } catch (InterruptedException e) { throw new RuntimeException(e); } } } } public static void main(String[] args){ Product product=new Product(); //生产者线程 ProducerThread p1=new ProducerThread(product); ProducerThread p2=new ProducerThread(product); ProducerThread p3=new ProducerThread(product); //消费者线程 ConsumerThread c1=new ConsumerThread(product); ConsumerThread c2=new ConsumerThread(product); ConsumerThread c3=new ConsumerThread(product); p1.start(); p2.start(); p3.start(); c1.start(); c2.start(); c3.start(); } }
import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class LockCondition { //消费者线程 static class ConsumerThread2 extends Thread{ private final Product2 product2; public ConsumerThread2(Product2 product2) { this.product2 = product2; setName("消费者"); } public void run(){ while(true){ try{ Thread.sleep((long) (1000*Math.random())); } catch (Exception e) { throw new RuntimeException(e); } product2.remove(); } } } //生产者线程 static class ProducerThread2 extends Thread{ private final Product2 product2; ProducerThread2(Product2 product2) { this.product2 = product2; setName("生产者"); } public void run(){ while(true){ try{ Thread.sleep((long) (1000*Math.random())); } catch (Exception e) { throw new RuntimeException(e); } product2.add(); } } } //产品类 static class Product2{ private int currentCount=0;//当前产品数量 private final Lock lock; private final Condition producerCondition; private final Condition consumerCondition; public Product2(Lock lock,Condition producerCondition,Condition consumerCondition){ this.lock=lock; this.producerCondition=producerCondition; this.consumerCondition=consumerCondition; } //生产产品 public void add(){ lock.lock(); try { int maxCount = 10; if (currentCount < maxCount) {//数量未达到上限生产一个产品当前数量加一 currentCount++; System.out.println(Thread.currentThread().getName() + "生产一件产品,当前产品库有" + currentCount + "个"); consumerCondition.signalAll();//唤醒等待的消费者 } else {//数量达到上限 //让生产者等待 try { producerCondition.await(); System.out.println(Thread.currentThread().getName()+"线程进入等待"); } catch (InterruptedException e) { throw new RuntimeException(e); } } } finally { lock.unlock(); } } //从产品库中取走产品 public void remove(){ lock.lock(); try { if(currentCount>0){ currentCount--; System.out.println(Thread.currentThread().getName()+"取出一件产品,当前产品库有"+currentCount+"件"); //唤醒等待的生产者 producerCondition.signalAll(); }else{//产品库数量为0 try{ consumerCondition.await();//让消费者等待 System.out.println(Thread.currentThread().getName()+"线程进入等待"); } catch (Exception e) { throw new RuntimeException(e); } } } finally { lock.unlock(); } } } public static void main(String[] args){ Lock lock=new ReentrantLock(); Condition producerCondition= lock.newCondition(); Condition consumerCondition= lock.newCondition(); Product2 product2=new Product2(lock,producerCondition,consumerCondition); //生产者线程 ProducerThread2 p1=new ProducerThread2(product2); ProducerThread2 p2=new ProducerThread2(product2); ProducerThread2 p3=new ProducerThread2(product2); //消费者线程 ConsumerThread2 c1=new ConsumerThread2(product2); ConsumerThread2 c2=new ConsumerThread2(product2); ConsumerThread2 c3=new ConsumerThread2(product2); p1.start(); p2.start(); p3.start(); c1.start(); c2.start(); c3.start(); } }