资讯专栏INFORMATION COLUMN

【全栈之路】JAVA基础课程四_生产者消费者问题(20190614v1.1)

everfight / 1096人阅读

摘要:寄语天眼之父南仁东,心无旁骛,为崇山峻岭间的中国天眼燃尽生命,看似一口大锅,天眼是世界上最大最灵敏的单口径射电望远镜,可以接受百亿光年外的电磁信号。南仁东总工程师执着追求科学梦想的精神,将激励一代又一代科技工作者继续奋斗,勇攀世界科技高峰。

欢迎进入JAVA基础课程

博客地址:https://segmentfault.com/a/11...
本系列文章将主要针对JAVA一些基础知识点进行讲解,为平时归纳所总结,不管是刚接触JAVA开发菜鸟还是业界资深人士,都希望对广大同行带来一些帮助。若有问题请及时留言或加QQ:243042162。

</>复制代码

  1. 寄语:
    “天眼”之父南仁东,心无旁骛,为崇山峻岭间的中国“天眼”燃尽生命,看似一口“大锅”,天眼是世界上最大、最灵敏的单口径射电望远镜,可以接受百亿光年外的电磁信号。南仁东总工程师执着追求科学梦想的精神,将激励一代又一代科技工作者继续奋斗,勇攀世界科技高峰。作为IT界的从业者,我们需要紧跟时代的步伐,踏过平庸,一生为科技筑梦。
生产者消费者问题

1. 背景

生产者消费者问题(Producer-consumer problem),也称有限缓冲问题(Bounded-buffer problem),是一个多线程同步问题的经典案例。生产者生成一定量的数据放到缓冲区中,然后重复此过程;与此同时,消费者也在缓冲区消耗这些数据。生产者和消费者之间必须保持同步,要保证生产者不会在缓冲区满时放入数据,消费者也不会在缓冲区空时消耗数据。不够完善的解决方法容易出现死锁的情况,此时进程都在等待唤醒。

2. 条件

生产者仅仅在仓储未满时候生产, 仓满则停止生产.

生产者在生产出可消费产品时候, 应该通知等待的消费者去消费.

消费者仅仅在仓储有产品时候才能消费, 仓空则等待.

消费者发现仓储没产品可消费时候会通知生产者生产.

3.实现方式

wait() / notify()方法

await() / signal()方法

BlockingQueue阻塞队列方法

Semaphore方法

PipedInputStream / PipedOutputStream

下面主要针对前面三种方式做代码实现

(1) wait() / notify()方法

</>复制代码

  1. public class ProducerMain {
  2. private static Integer count=0;
  3. private final Integer full=10;
  4. private static String LOCK="LOCK";
  5. class Producer implements Runnable{
  6. @Override
  7. public void run() {
  8. // for(int i=0;i<10;i++){
  9. // try {
  10. // Thread.sleep(3000);
  11. // } catch (InterruptedException e) {
  12. // e.printStackTrace();
  13. // }
  14. // }
  15. synchronized (LOCK){
  16. while(count==full){
  17. try {
  18. LOCK.wait();
  19. } catch (InterruptedException e) {
  20. e.printStackTrace();
  21. }
  22. }
  23. count++;
  24. System.out.println(Thread.currentThread().getName()+"生产者生产,目前共生产了:"+count);
  25. LOCK.notifyAll();
  26. }
  27. }
  28. }
  29. class Consumer implements Runnable{
  30. @Override
  31. public void run() {
  32. synchronized (LOCK){
  33. while (count==0){
  34. try {
  35. LOCK.wait();
  36. } catch (InterruptedException e) {
  37. e.printStackTrace();
  38. }
  39. }
  40. count--;
  41. System.out.println(Thread.currentThread().getName()+"生产者消费,目前共剩余:"+count);
  42. LOCK.notifyAll();
  43. }
  44. }
  45. }
  46. public static void main(String[] args) {
  47. ProducerMain producer = new ProducerMain();
  48. new Thread(producer.new Producer()).start();
  49. new Thread(producer.new Consumer()).start();
  50. new Thread(producer.new Producer()).start();
  51. new Thread(producer.new Consumer()).start();
  52. new Thread(producer.new Producer()).start();
  53. new Thread(producer.new Consumer()).start();
  54. new Thread(producer.new Producer()).start();
  55. new Thread(producer.new Consumer()).start();
  56. }
  57. }

输出结果

</>复制代码

  1. Thread-0生产者生产,目前共生产了:1
  2. Thread-5生产者消费,目前共剩余:0
  3. Thread-2生产者生产,目前共生产了:1
  4. Thread-7生产者消费,目前共剩余:0
  5. Thread-6生产者生产,目前共生产了:1
  6. Thread-1生产者消费,目前共剩余:0
  7. Thread-4生产者生产,目前共生产了:1
  8. Thread-3生产者消费,目前共剩余:0

(2)await() / signal()方法

</>复制代码

  1. public class ReentrantLockDemo {
  2. private static Integer count = 0;
  3. private final Integer FULL = 10;
  4. final Lock lock = new ReentrantLock();
  5. final Condition NotFull = lock.newCondition();
  6. final Condition NotEmpty = lock.newCondition();
  7. class Producer implements Runnable {
  8. @Override
  9. public void run() {
  10. for (int i = 0; i < 10; i++) {
  11. try {
  12. Thread.sleep(3000);
  13. } catch (Exception e) {
  14. e.printStackTrace();
  15. }
  16. lock.lock();
  17. try {
  18. while (count == FULL) {
  19. try {
  20. NotFull.await();
  21. } catch (InterruptedException e) {
  22. // TODO Auto-generated catch block
  23. e.printStackTrace();
  24. }
  25. }
  26. count++;
  27. System.out.println(Thread.currentThread().getName()
  28. + "生产者生产,目前总共有" + count);
  29. NotEmpty.signal();
  30. } finally {
  31. lock.unlock();
  32. }
  33. }
  34. }
  35. }
  36. class Consumer implements Runnable {
  37. @Override
  38. public void run() {
  39. for (int i = 0; i < 10; i++) {
  40. try {
  41. Thread.sleep(3000);
  42. } catch (InterruptedException e1) {
  43. e1.printStackTrace();
  44. }
  45. lock.lock();
  46. try {
  47. while (count == 0) {
  48. try {
  49. NotEmpty.await();
  50. } catch (Exception e) {
  51. // TODO: handle exception
  52. e.printStackTrace();
  53. }
  54. }
  55. count--;
  56. System.out.println(Thread.currentThread().getName()
  57. + "消费者消费,目前总共有" + count);
  58. NotFull.signal();
  59. } finally {
  60. lock.unlock();
  61. }
  62. }
  63. }
  64. }
  65. public static void main(String[] args) throws Exception {
  66. ReentrantLockDemo hosee = new ReentrantLockDemo();
  67. new Thread(hosee.new Producer()).start();
  68. new Thread(hosee.new Consumer()).start();
  69. new Thread(hosee.new Producer()).start();
  70. new Thread(hosee.new Consumer()).start();
  71. new Thread(hosee.new Producer()).start();
  72. new Thread(hosee.new Consumer()).start();
  73. new Thread(hosee.new Producer()).start();
  74. new Thread(hosee.new Consumer()).start();
  75. }
  76. }

输出结果

</>复制代码

  1. Thread-0生产者生产,目前总共有1
  2. Thread-2生产者生产,目前总共有2
  3. Thread-1消费者消费,目前总共有1
  4. Thread-7消费者消费,目前总共有0
  5. Thread-6生产者生产,目前总共有1
  6. Thread-5消费者消费,目前总共有0
  7. Thread-4生产者生产,目前总共有1
  8. Thread-3消费者消费,目前总共有0
  9. Thread-0生产者生产,目前总共有1
  10. Thread-2生产者生产,目前总共有2
  11. Thread-1消费者消费,目前总共有1
  12. Thread-6生产者生产,目前总共有2
  13. Thread-7消费者消费,目前总共有1
  14. Thread-5消费者消费,目前总共有0
  15. Thread-4生产者生产,目前总共有1
  16. Thread-3消费者消费,目前总共有0
  17. Thread-0生产者生产,目前总共有1
  18. Thread-2生产者生产,目前总共有2
  19. Thread-1消费者消费,目前总共有1
  20. Thread-7消费者消费,目前总共有0
  21. Thread-6生产者生产,目前总共有1
  22. Thread-5消费者消费,目前总共有0
  23. Thread-4生产者生产,目前总共有1
  24. Thread-3消费者消费,目前总共有0
  25. Thread-0生产者生产,目前总共有1
  26. Thread-2生产者生产,目前总共有2
  27. Thread-1消费者消费,目前总共有1
  28. Thread-7消费者消费,目前总共有0
  29. Thread-6生产者生产,目前总共有1
  30. Thread-5消费者消费,目前总共有0
  31. Thread-4生产者生产,目前总共有1
  32. Thread-3消费者消费,目前总共有0
  33. Thread-0生产者生产,目前总共有1
  34. Thread-2生产者生产,目前总共有2
  35. Thread-1消费者消费,目前总共有1
  36. Thread-6生产者生产,目前总共有2
  37. Thread-7消费者消费,目前总共有1
  38. Thread-5消费者消费,目前总共有0
  39. Thread-4生产者生产,目前总共有1
  40. Thread-3消费者消费,目前总共有0
  41. Thread-2生产者生产,目前总共有1
  42. Thread-0生产者生产,目前总共有2
  43. Thread-1消费者消费,目前总共有1
  44. Thread-7消费者消费,目前总共有0
  45. Thread-6生产者生产,目前总共有1
  46. Thread-5消费者消费,目前总共有0
  47. Thread-4生产者生产,目前总共有1
  48. Thread-3消费者消费,目前总共有0
  49. Thread-2生产者生产,目前总共有1
  50. Thread-0生产者生产,目前总共有2
  51. Thread-1消费者消费,目前总共有1
  52. Thread-6生产者生产,目前总共有2
  53. Thread-7消费者消费,目前总共有1
  54. Thread-5消费者消费,目前总共有0
  55. Thread-4生产者生产,目前总共有1
  56. Thread-3消费者消费,目前总共有0
  57. Thread-2生产者生产,目前总共有1
  58. Thread-0生产者生产,目前总共有2
  59. Thread-1消费者消费,目前总共有1
  60. Thread-6生产者生产,目前总共有2
  61. Thread-7消费者消费,目前总共有1
  62. Thread-5消费者消费,目前总共有0
  63. Thread-4生产者生产,目前总共有1
  64. Thread-3消费者消费,目前总共有0
  65. Thread-2生产者生产,目前总共有1
  66. Thread-0生产者生产,目前总共有2
  67. Thread-1消费者消费,目前总共有1
  68. Thread-6生产者生产,目前总共有2
  69. Thread-7消费者消费,目前总共有1
  70. Thread-4生产者生产,目前总共有2
  71. Thread-5消费者消费,目前总共有1
  72. Thread-3消费者消费,目前总共有0
  73. Thread-0生产者生产,目前总共有1
  74. Thread-2生产者生产,目前总共有2
  75. Thread-1消费者消费,目前总共有1
  76. Thread-6生产者生产,目前总共有2
  77. Thread-7消费者消费,目前总共有1
  78. Thread-5消费者消费,目前总共有0
  79. Thread-4生产者生产,目前总共有1
  80. Thread-3消费者消费,目前总共有0

(3)BlockingQueue阻塞队列方法

</>复制代码

  1. public class BlockingQueueMain {
  2. private static Integer count = 0;
  3. final BlockingQueue bq = new ArrayBlockingQueue(10);
  4. class Producer implements Runnable {
  5. @Override
  6. public void run() {
  7. for (int i = 0; i < 10; i++) {
  8. try {
  9. Thread.sleep(3000);
  10. } catch (Exception e) {
  11. e.printStackTrace();
  12. }
  13. try {
  14. bq.put(1);
  15. count++;
  16. System.out.println(Thread.currentThread().getName()
  17. + "生产者生产,目前总共有" + count);
  18. } catch (InterruptedException e) {
  19. // TODO Auto-generated catch block
  20. e.printStackTrace();
  21. }
  22. }
  23. }
  24. }
  25. class Consumer implements Runnable {
  26. @Override
  27. public void run() {
  28. for (int i = 0; i < 10; i++) {
  29. try {
  30. Thread.sleep(3000);
  31. } catch (InterruptedException e1) {
  32. e1.printStackTrace();
  33. }
  34. try {
  35. bq.take();
  36. count--;
  37. System.out.println(Thread.currentThread().getName()
  38. + "消费者消费,目前总共有" + count);
  39. } catch (Exception e) {
  40. // TODO: handle exception
  41. e.printStackTrace();
  42. }
  43. }
  44. }
  45. }
  46. public static void main(String[] args) throws Exception {
  47. BlockingQueueMain hosee = new BlockingQueueMain();
  48. new Thread(hosee.new Producer()).start();
  49. new Thread(hosee.new Consumer()).start();
  50. new Thread(hosee.new Producer()).start();
  51. new Thread(hosee.new Consumer()).start();
  52. new Thread(hosee.new Producer()).start();
  53. new Thread(hosee.new Consumer()).start();
  54. new Thread(hosee.new Producer()).start();
  55. new Thread(hosee.new Consumer()).start();
  56. }
  57. }

输出结果

</>复制代码

  1. Thread-1消费者消费,目前总共有0
  2. Thread-4生产者生产,目前总共有1
  3. Thread-0生产者生产,目前总共有0
  4. Thread-5消费者消费,目前总共有0
  5. Thread-3消费者消费,目前总共有0
  6. Thread-2生产者生产,目前总共有1
  7. Thread-6生产者生产,目前总共有1
  8. Thread-7消费者消费,目前总共有0
  9. Thread-4生产者生产,目前总共有1
  10. Thread-1消费者消费,目前总共有0
  11. Thread-0生产者生产,目前总共有1
  12. Thread-5消费者消费,目前总共有0
  13. Thread-2生产者生产,目前总共有1
  14. Thread-3消费者消费,目前总共有0
  15. Thread-6生产者生产,目前总共有0
  16. Thread-7消费者消费,目前总共有0
  17. Thread-4生产者生产,目前总共有0
  18. Thread-1消费者消费,目前总共有0
  19. Thread-0生产者生产,目前总共有1
  20. Thread-5消费者消费,目前总共有0
  21. Thread-2生产者生产,目前总共有1
  22. Thread-3消费者消费,目前总共有0
  23. Thread-6生产者生产,目前总共有1
  24. Thread-7消费者消费,目前总共有0
  25. Thread-4生产者生产,目前总共有1
  26. Thread-1消费者消费,目前总共有0
  27. Thread-0生产者生产,目前总共有1
  28. Thread-5消费者消费,目前总共有0
  29. Thread-2生产者生产,目前总共有1
  30. Thread-3消费者消费,目前总共有0
  31. Thread-6生产者生产,目前总共有1
  32. Thread-7消费者消费,目前总共有0
  33. Thread-4生产者生产,目前总共有2
  34. Thread-0生产者生产,目前总共有1
  35. Thread-1消费者消费,目前总共有0
  36. Thread-5消费者消费,目前总共有1
  37. Thread-2生产者生产,目前总共有1
  38. Thread-3消费者消费,目前总共有0
  39. Thread-6生产者生产,目前总共有1
  40. Thread-7消费者消费,目前总共有0

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/104683.html

相关文章

  • 全栈之路JAVA基础课程_产者费者问题20190614v1.1

    摘要:寄语天眼之父南仁东,心无旁骛,为崇山峻岭间的中国天眼燃尽生命,看似一口大锅,天眼是世界上最大最灵敏的单口径射电望远镜,可以接受百亿光年外的电磁信号。南仁东总工程师执着追求科学梦想的精神,将激励一代又一代科技工作者继续奋斗,勇攀世界科技高峰。 欢迎进入JAVA基础课程 博客地址:https://segmentfault.com/a/11...本系列文章将主要针对JAVA一些基础知识点进行...

    lemon 评论0 收藏0
  • 全栈之路JAVA基础课程_哲学家就餐问题20190614v1.2)

    摘要:欢迎进入基础课程博客地址本系列文章将主要针对一些基础知识点进行讲解,为平时归纳所总结,不管是刚接触开发菜鸟还是业界资深人士,都希望对广大同行带来一些帮助。若有问题请及时留言或加。 欢迎进入JAVA基础课程 博客地址:https://blog.csdn.net/houjiyu...本系列文章将主要针对JAVA一些基础知识点进行讲解,为平时归纳所总结,不管是刚接触JAVA开发菜鸟还是业界...

    Mr_houzi 评论0 收藏0
  • 全栈之路JAVA基础课程_哲学家就餐问题20190614v1.2)

    摘要:欢迎进入基础课程博客地址本系列文章将主要针对一些基础知识点进行讲解,为平时归纳所总结,不管是刚接触开发菜鸟还是业界资深人士,都希望对广大同行带来一些帮助。若有问题请及时留言或加。 欢迎进入JAVA基础课程 博客地址:https://blog.csdn.net/houjiyu...本系列文章将主要针对JAVA一些基础知识点进行讲解,为平时归纳所总结,不管是刚接触JAVA开发菜鸟还是业界...

    JerryZou 评论0 收藏0
  • 全栈之路JAVA基础课程_多线程和死锁(20190614v1.0)

    摘要:一个进程可以有多个线程。线程又叫做轻量级进程。这样两个进程相互无休止地等待下去,均无法继续执行,此时两个进程陷入死锁状态。不剥夺条件进程所获得的资源在未使用完毕之前,不能被其他进程强行夺走,即只能由获得该资源的进程自己来释放只能是主动释放。 欢迎进入JAVA基础课程 博客地址:https://blog.csdn.net/houjiyu...本系列文章将主要针对JAVA一些基础知识点进...

    Allen 评论0 收藏0
  • 全栈之路JAVA基础课程_多线程和死锁(20190614v1.0)

    摘要:一个进程可以有多个线程。线程又叫做轻量级进程。这样两个进程相互无休止地等待下去,均无法继续执行,此时两个进程陷入死锁状态。不剥夺条件进程所获得的资源在未使用完毕之前,不能被其他进程强行夺走,即只能由获得该资源的进程自己来释放只能是主动释放。 欢迎进入JAVA基础课程 博客地址:https://blog.csdn.net/houjiyu...本系列文章将主要针对JAVA一些基础知识点进...

    warnerwu 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<