java生产者消费者限量版_Java实现生产者消费者

方法1:最简单--利用LinkedBlockingQueue

队列具有先进先出的特点,成为经常应用于生产-消费者模式的数据结构。

1.将一个对象放到队列尾部,如果队列已满,就等待直到有空闲节点。 ——put()方法

2.从队列头部取一个对象,如果没有对象,就等待直到有对象可取。 ——take()方法

3.在存取队列的过程中,锁定队列对象,不允许其它线程访问队列。——使得它是线程安全的

下面的代码适用于多个生产者、多个消费者。

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 //Producer.java

2 importjava.util.concurrent.BlockingQueue;3

4 /*

5 * Usage example, based on a typical producer-consumer scenario.6 * Note that a BlockingQueue can safely be used with multiple7 * producers and multiple consumers.8 *

9  */

10 class Producer implementsRunnable {11 private BlockingQueuequeue;12

13 Producer(BlockingQueueq) {14 queue =q;15 }16

17 public voidrun() {18 try{19 while (true) {20 queue.put(produce());21 Thread.sleep(1);22 System.out.println("+1 Produce an Object:" + "生产者size:"

23 +queue.size());24 }25 } catch(InterruptedException ex) {26 System.out.println("生产者结束!");27 }28 }29

30 Object produce() {31 return newObject();32 }33 }

Pruducer.java

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 //Consumer.java

2 importjava.util.concurrent.BlockingQueue;3

4 class Consumer implementsRunnable {5 private BlockingQueuequeue;6

7 Consumer(BlockingQueueq) {8 queue =q;9 }10

11 public voidrun() {12 try{13 while (true) {14 consume(queue.take());15 Thread.sleep(10);16 System.out.println("-1 Consumer an Object:" + "size:"+queue.size());17 }18 } catch(InterruptedException ex) {19 System.out.println("消费者结束!");20 }21 }22

23 voidconsume(Object x) {24 }25 }

Consumer.java

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 importjava.util.concurrent.BlockingQueue;2 importjava.util.concurrent.LinkedBlockingQueue;3

4 classMain {5 public static voidmain(String[] args) {6 BlockingQueue q = new LinkedBlockingQueue();//SomeQueueImplementation();

7 Producer p = newProducer(q);8 Consumer c1 = newConsumer(q);9 Consumer c2 = newConsumer(q);10 Thread pth = newThread(p);11 pth.start();12 newThread(c1).start();13 newThread(c2).start();14 try{15 Thread.sleep(50);16 pth.interrupt();17 } catch(InterruptedException e) {18 }19 }20 }

Main.java

方法2:不采用BlockingQueue,利用lock、Condition来实现

思路:

利用可重用的LinkedList来存放资源,生产者addLast(),消费者removeFirst()。

使用ReentrantLock()来实现消费者和生产者的同步;//可重用的互斥锁

思考:为什么使用了lock后,还使用了它的2个newCondition,这样做有什么好处?

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 import java.util.*;2 importjava.util.concurrent.locks.Condition;3 importjava.util.concurrent.locks.Lock;4 importjava.util.concurrent.locks.ReentrantLock;5

6 public classProducerConsumer {7 private static final LinkedList buffer = new LinkedList();8 private static final int BUFFERSIZE = 10;9 private static Lock lock = new ReentrantLock();//可重用的互斥锁

10 private static Condition NotFull =lock.newCondition();11 private static Condition NotEmpty =lock.newCondition();12

13 static class Producer extendsThread {14 public voidrun() {15 while (true) {16 //lock

17 lock.lock();18 if (buffer.size() ==BUFFERSIZE) {19 System.out.println("BUffer is fulls");20 try{21 NotFull.await();22 } catch(InterruptedException e) {23 e.printStackTrace();24 }25 } else{26 buffer.addLast(1);27 NotEmpty.signal();28 }29 lock.unlock();30 //unlock

31 }32 }33 }34

35 static class Consumer extendsThread {36 public voidrun() {37 while (true) {38 //lock

39 lock.lock();40 if (buffer.size() == 0) {41 System.out.println("BUffer is empty");42 try{43 NotEmpty.await();44 } catch(InterruptedException e) {45 e.printStackTrace();46 }47 } else{48 buffer.removeFirst();49 NotFull.signal();50 }51 //unlock

52 lock.unlock();53 }54 }55 }56

57 public static voidmain(String[] args){58 newConsumer().start();59 newProducer().start();60 }61 }

ProducerConsumer .java

关于Java线程的lock、condition、synchronized的小小总结:

1.synchronized简单易用,但是功能受局限,无法满足复杂的同步机制,比如“读者写者问题”:多个读者线程是不互斥的。

2.lock以更优雅的方式来解决线程同步,比如读写锁ReadWriteLock。

3.Condition解决线程间通信,为不同的线程建立不同的条件。

Condition可以替代传统的线程间通信,用await()替换wait(),用signal()替换notify(),用signalAll()替换notifyAll()。

——为什么方法名不直接叫wait()/notify()/nofityAll()?因为Object的这几个方法是final的,不可重写!

Condition实现了BlockingQueue的功能。

看看BlockingQueue的继承和实现。

31dab380cbe177efcbb29a133bef536d.png

一般的锁Lock的实现:注意ReadLock、WriteLock是内部的静态类,只有ReentrantReadWriteLock类可以调用。

af82a81c8c83eb4e5dbd62254da3183c.png

读写的锁ReadWriteLock

baa23024ec82ac9d315964aec242db52.png

思考:OS的信号量是什么,线程通信的方式有哪些?共享变量和消息传递。

信号量与互斥锁有什么联系?

By BYRHuangQiang2014-03-18 09:05:30

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值