zoukankan      html  css  js  c++  java
  • 浅谈Java简单实现的生产者与消费者问题

    一、面对生产者和消费者的问题,首先我们得明白几点

    生产者:生产数据;
    消费者:消费数据。
    消费者在没有数据可供消费的情况下,不能消费;
    生产者在原数据没有被消费掉的情况下,不能生产新数据。
    假设,数据空间只有一个。
    实际上,如果实现了正确的生产和消费,则,两个线程应该是严格的交替执行。

    synchronized关键字若用在代码中,形成一个同步块,且,必须要执行锁:
        synchronized (锁对象) {
            同步块
        }
    同步块使得锁对象称为thread monitor
    二、代码实现:

    1.首先我们建立一个生产者和消费者共同拥有的锁的类:

    1 package com.mec.about_procuder_customer.core;
    2 
    3 public class ProcuderCustomer {
    4     //初始状态的数据为0个
    5     protected static volatile int count = 0;
    6     //执行锁
    7     protected final static Object lock = new Object();
    8 }

    上述代码有一个关键字volatile,它是保证线程之间有序的一种方式,最重要也是最直接的是禁止寄存器优化。就是如果线程run方法中只是一个循环,并没有执行语句,那么,这个线程将不会执行。

    2.我们再来建立一个生产者的类:

     1 package com.mec.about_procuder_customer.core;
     2 
     3 //生产者
     4 public class Procuder extends ProcuderCustomer implements Runnable {
     5     
     6     //存放数据的空间
     7     private int[] dataSpace;
     8     
     9     public Procuder(int[] dataSpace, String threadName) {
    10         this.dataSpace = dataSpace;
    11         //启动线程
    12         new Thread(this, threadName).start();
    13     }
    14     
    15     @Override
    16     public void run() {
    17         int i = 0;
    18         
    19         while (true) {
    20             synchronized (lock) {
    21                 //判断是否空间已满
    22                 if (count < dataSpace.length) {
    23                     //产生者放数据
    24                     dataSpace[count] = i++;
    25                     System.out.println("[" + Thread.currentThread().getName()
    26                             + "]线程生产了一个数:" + dataSpace[count++]
    27                             + " " + count);
    28                     try {
    29                         //只是为了看的清楚,沉睡2秒
    30                         Thread.sleep(200);
    31                     } catch (InterruptedException e) {
    32                         e.printStackTrace();
    33                     }
    34                     //唤醒消费者
    35                     lock.notify();
    36                 } else {
    37                     try {
    38                         //使自己处于阻塞状态
    39                         lock.wait();
    40                     } catch (InterruptedException e) {
    41                     e.printStackTrace();
    42                     }
    43                 }
    44             }
    45         }
    46     }
    47 }

    3.建立消费者的类:

     1 package com.mec.about_procuder_customer.core;
     2 
     3 //消费者
     4 public class Customer extends ProcuderCustomer implements Runnable {
     5     //存放数据的空间
     6     private int[] dataSpace;
     7     
     8     public Customer(int[] dataSpace, String threadName) {
     9         this.dataSpace = dataSpace;
    10         //启动线程
    11         new Thread(this, threadName).start();
    12     }
    13     
    14     @Override
    15     public void run() {
    16         while (true) {
    17             //加锁
    18             synchronized (lock) {
    19                 //判断是否有数据
    20                 if (count > 0) {
    21                     System.out.println("[" + Thread.currentThread().getName()
    22                             + "]线程消费了一个数:" + dataSpace[--count]);
    23                     //唤醒生产者
    24                     lock.notifyAll();
    25                 } else {
    26                     try {
    27                         //使自己处于阻塞状态
    28                         lock.wait();
    29                     } catch (InterruptedException e) {
    30                         e.printStackTrace();
    31                     }
    32                 }
    33             }
    34         }
    35     }
    36 
    37 }

    4.测试类

     1 package com.mec.about_procuder_customer.test;
     2 
     3 import com.mec.about_procuder_customer.core.Customer;
     4 import com.mec.about_procuder_customer.core.Procuder;
     5 
     6 public class Test {
     7 
     8     public static void main(String[] args) {
     9         int[] data = new int[10];
    10         new Procuder(data, "生产者1");
    11         new Procuder(data, "生产者2");
    12         new Customer(data, "消费者");
    13     }
    14 
    15 }

    运行结果:

  • 相关阅读:
    CVS是版本控制
    AMD CPU 看清楚
    亚洲卫视 > 技术讲义
    Windows下安装APM大全
    Windows Server 2003的几个奇怪的设置问题
    TortoiseCVS 简明流程实例
    MESSAGEBOX() 函数
    用于多表更新
    H1B签证问题
    一些好的表格
  • 原文地址:https://www.cnblogs.com/youdiaodaxue16/p/9949941.html
Copyright © 2011-2022 走看看