Java的高并发编程系列(六)生产者消费者面试题解析
2018-03-29 15:08
190 查看
面试题:写一个固定容量同步容器,拥有Put和get方法,以及getCount方法能够支持两个生产者线程以及10个消费者线程的阻塞调用
使用wait和notify/notifyAll来实现:
使用Lock和Condition来实现,对比两种方式,Condition的方式可以更加精确的指定哪些线程被唤醒。
使用wait和notify/notifyAll来实现:
public class MyContainer1 <T>{ private final LinkedList<T> lists = new LinkedList<>(); private final int MAX = 10; //最多10个元素 private int count = 0; public synchronized void put(T t){ while (lists.size() == MAX) { //while正常情况下和wait()一起使用, try { this.wait(); //effective java } catch (InterruptedException e) { e.printStackTrace(); } } lists.add(t); ++ count; this.notifyAll(); //通知消费者线程进行消费 } public synchronized T get(){ T t = null; while (lists.size() == 0) { try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } t = lists.removeFirst(); count --; this.notifyAll(); //通知生产者进行生产 return t; } public static void main(String[] args) { MyContainer1<String> c = new MyContainer1<>(); //启动消费者线程 for (int i = 0; i < 100; i++) { new Thread(()->{ for (int j = 0; j < 5; j++) { System.out.println(c.get()); } }, "c" + i).start(); } try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); } //启动生产者线程 for (int i = 0; i < 2; i++) { new Thread(()->{ for (int j = 0; j < 25; j++) { c.put(Thread.currentThread().getName() + "" + j); } }, "p" + i).start(); } } }
使用Lock和Condition来实现,对比两种方式,Condition的方式可以更加精确的指定哪些线程被唤醒。
public class MyContainer2<T> { private final LinkedList<T> lists = new LinkedList<>(); private final int MAX = 10; private int count = 0; private Lock lock = new ReentrantLock(); private Condition producer = lock.newCondition(); private Condition consumer = lock.newCondition(); public void put(T t){ try { lock.lock(); while (lists.size() == MAX) { producer.await(); } lists.add(t); ++count; consumer.signalAll(); //通知消费者线程进行消费 } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } public T get(){ T t = null; try { lock.lock(); while (lists.size() == 0) { consumer.await(); } lists.removeFirst(); count --; producer.signalAll(); //通知生产者进行生产 } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } return t; } public static void main(String[] args) { MyContainer2<String> c = new MyContainer2<>(); //启消费者线程 for (int i = 0; i < 100; i++) { new Thread(()->{ for (int j = 0; j < 5; j++) { System.out.println(c.get()); } }, "c" + i).start(); } try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); } //启动生产者线程 for (int i = 0; i < 2; i++) { new Thread(()->{ for (int j = 0; j < 25; j++) { c.put(Thread.currentThread().getName() + "" + j); } }, "p" + i).start(); } } }
相关文章推荐
- JAVA基础再回首(二十五)——Lock锁的使用、死锁问题、多线程生产者和消费者、线程池、匿名内部类使用多线程、定时器、面试题
- Java 线程与并发研究系列五(生产者与消费者)
- Java多线程系列(三)—生产者消费者模型
- java 多线程并发系列之 生产者消费者模式的两种实现
- java 多线程并发系列之 生产者消费者模式的两种实现
- Java 并发编程(四)阻塞队列和生产者-消费者模式
- Java多线程系列-Queue、BlockingQueue以及利用BlockingQueue实现生产者/消费者模型
- JAVA多线程系列之生产者消费者
- java线程深度解析(五)——并发模型(生产者-消费者)
- JAVA基础再回首(二十五)——Lock锁的使用、死锁问题、多线程生产者和消费者、线程池、匿名内部类使用多线程、定时器、面试题
- java 多线程并发系列之 生产者消费者模式的两种实现
- JAVA基础再回首(二十五)——Lock锁的使用、死锁问题、多线程生产者和消费者、线程池、匿名内部类使用多线程、定时器、面试题
- java线程深度解析(五)——并发模型(生产者-消费者)
- 多生产者--多消费者 显示锁实现同步 java实现
- kafka生产者和消费者的javaAPI的示例代码
- 【Java集合系列四】HashSet和LinkedHashSet解析
- Java 线程的基本概念(模仿生产者与消费者的问题)
- 生产者消费者问题的Java实现
- java模拟生产者消费者问题
- Java 集合系列13之 WeakHashMap详细介绍(源码解析)和使用示例