浅谈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 }

运行结果:

原文地址:https://www.cnblogs.com/youdiaodaxue16/p/9949941.html

时间: 2024-08-01 03:03:17

浅谈Java简单实现的生产者与消费者问题的相关文章

【转】浅谈Java中的equals和==

浅谈Java中的equals和== 在初学Java时,可能会经常碰到下面的代码: 1 String str1 = new String("hello"); 2 String str2 = new String("hello"); 3 4 System.out.println(str1==str2); 5 System.out.println(str1.equals(str2)); 为什么第4行和第5行的输出结果不一样?==和equals方法之间的区别是什么?如果在初

浅谈java异常[Exception]

本文转自:focusJ 一. 异常的定义 在<java编程思想>中这样定义 异常:阻止当前方法或作用域继续执行的问题.虽然java中有异常处理机制,但是要明确一点,决不应该用"正常"的态度来看待异常.绝对一点说异常就是某种意义上的错误,就是问题,它可能会导致程序失败.之所以java要提出异常处理机制,就是要告诉开发人员,你的程序出现了不正常的情况,请注意. 记得当初学习java的时候,异常总是搞不太清楚,不知道这个异常是什么意思,为什么会有这个机制?但是随着知识的积累逐渐也

浅谈Java中的equals和==

浅谈Java中的equals和== 在初学Java时,可能会经常碰到下面的代码: 1 String str1 = new String("hello"); 2 String str2 = new String("hello"); 3 4 System.out.println(str1==str2); 5 System.out.println(str1.equals(str2)); 为什么第4行和第5行的输出结果不一样?==和equals方法之间的区别是什么?如果在初

浅谈Java中的hashcode方法 - 海 子

浅谈Java中的hashcode方法 哈希表这个数据结构想必大多数人都不陌生,而且在很多地方都会利用到hash表来提高查找效率.在Java的Object类中有一个方法: public native int hashCode(); 根据这个方法的声明可知,该方法返回一个int类型的数值,并且是本地方法,因此在Object类中并没有给出具体的实现. 为何Object类需要这样一个方法?它有什么作用呢?今天我们就来具体探讨一下hashCode方法. 一.hashCode方法的作用 对于包含容器类型的程

浅谈Java中的深拷贝和浅拷贝

浅谈Java中的深拷贝和浅拷贝(转载) 原文链接: http://blog.csdn.net/tounaobun/article/details/8491392 假如说你想复制一个简单变量.很简单: [java] view plaincopyprint? int apples = 5; int pears = apples; int apples = 5; int pears = apples; 不仅仅是int类型,其它七种原始数据类型(boolean,char,byte,short,float

浅谈 Java 主流开源类库解析 XML

在大型项目编码推进中,涉及到 XML 解析问题时,大多数程序员都不太会选用底层的解析方式直接编码. 主要存在编码复杂性.难扩展.难复用....,但如果你是 super 程序员或是一个人的项目,也不妨一试. Jdom/Dom4j/Xstream... 基于底层解析方式重新组织封装的开源类库,简洁明了的 API,稳定高效的运行表现. Dom4j 基于 JAXP 解析方式,性能优异.功能强大.极易使用的优秀框架.想了解底层解析方式请翻看:浅谈 Java XML 底层解析方式 Jdom 你细看内部代码,

浅谈java类集框架和数据结构(2)

继续上一篇浅谈java类集框架和数据结构(1)的内容 上一篇博文简介了java类集框架几大常见集合框架,这一篇博文主要分析一些接口特性以及性能优化. 一:List接口 List是最常见的数据结构了,主要有最重要的三种实现:ArrayList,Vector,LinkedList,三种List均来自AbstracList的实现,而AbstracList直接实现了List接口,并拓展自AbstractCollection. 在三种实现中,ArrayList和Vector使用了数组实现,可以认为这两个是

浅谈Java中set.map.List的区别

就学习经验,浅谈Java中的Set,List,Map的区别,对JAVA的集合的理解是想对于数组: 数组是大小固定的,并且同一个数组只能存放类型一样的数据(基本类型/引用类型),JAVA集合可以存储和操作数目不固定的一组数据. 所有的JAVA集合都位于 java.util包中! JAVA集合只能存放引用类型的的数据,不能存放基本数据类型. JAVA集合主要分为三种类型: Set(集) List(列表) Map(映射) Collection 接口 :Collection是最基本的集合接口,声明了适用

浅谈JAVA中的“hashcode()”方法

浅谈Java中的hashcode方法 哈希表这个数据结构想必大多数人都不陌生,而且在很多地方都会利用到hash表来提高查找效率.在Java的Object类中有一个方法: public native int hashCode(); 为何Object类需要这样一个方法?它有什么作用呢?今天我们就来具体探讨一下hashCode方法. 根据这个方法的声明可知,该方法返回一个int类型的数值,并且是本地方法,因此在Object类中并没有给出具体的实现. 一.hashCode方法的作用 对于包含容器类型的程