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

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

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

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

 package com.mec.about_procuder_customer.core;

 public class ProcuderCustomer {
//初始状态的数据为0个
protected static volatile int count = 0;
//执行锁
protected final static Object lock = new Object();
}

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

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

 package com.mec.about_procuder_customer.core;

 //生产者
public class Procuder extends ProcuderCustomer implements Runnable { //存放数据的空间
private int[] dataSpace; public Procuder(int[] dataSpace, String threadName) {
this.dataSpace = dataSpace;
//启动线程
new Thread(this, threadName).start();
} @Override
public void run() {
int i = 0; while (true) {
synchronized (lock) {
//判断是否空间已满
if (count < dataSpace.length) {
//产生者放数据
dataSpace[count] = i++;
System.out.println("[" + Thread.currentThread().getName()
+ "]线程生产了一个数:" + dataSpace[count++]
+ " " + count);
try {
//只是为了看的清楚,沉睡2秒
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
//唤醒消费者
lock.notify();
} else {
try {
//使自己处于阻塞状态
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}

3.建立消费者的类:

 package com.mec.about_procuder_customer.core;

 //消费者
public class Customer extends ProcuderCustomer implements Runnable {
//存放数据的空间
private int[] dataSpace; public Customer(int[] dataSpace, String threadName) {
this.dataSpace = dataSpace;
//启动线程
new Thread(this, threadName).start();
} @Override
public void run() {
while (true) {
//加锁
synchronized (lock) {
//判断是否有数据
if (count > 0) {
System.out.println("[" + Thread.currentThread().getName()
+ "]线程消费了一个数:" + dataSpace[--count]);
//唤醒生产者
lock.notifyAll();
} else {
try {
//使自己处于阻塞状态
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
} }

4.测试类:

 package com.mec.about_procuder_customer.test;

 import com.mec.about_procuder_customer.core.Customer;
import com.mec.about_procuder_customer.core.Procuder; public class Test { public static void main(String[] args) {
int[] data = new int[10];
new Procuder(data, "生产者1");
new Procuder(data, "生产者2");
new Customer(data, "消费者");
} }

运行结果:

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

  1. 浅谈Java的throw与throws

    转载:http://blog.csdn.net/luoweifu/article/details/10721543 我进行了一些加工,不是本人原创但比原博主要更完善~ 浅谈Java异常 以前虽然知道一 ...

  2. 浅谈Java中的equals和==(转)

    浅谈Java中的equals和== 在初学Java时,可能会经常碰到下面的代码: 1 String str1 = new String("hello"); 2 String str ...

  3. 浅谈Java中的equals和==

    浅谈Java中的equals和== 在初学Java时,可能会经常碰到下面的代码: String str1 = new String("hello"); String str2 = ...

  4. 浅谈java性能分析

    浅谈java性能分析,效能分析 在老师强烈的要求下做了效能分析,对上次写过的词频统计的程序进行分析以及改进. 对于效能分析:我个人很浅显的认为就是程序的运行效率,代码的执行效率等等. java做性能测 ...

  5. 浅谈Java中的深拷贝和浅拷贝(转载)

    浅谈Java中的深拷贝和浅拷贝(转载) 原文链接: http://blog.csdn.net/tounaobun/article/details/8491392 假如说你想复制一个简单变量.很简单: ...

  6. !! 浅谈Java学习方法和后期面试技巧

    浅谈Java学习方法和后期面试技巧 昨天查看3303回复33 部落用户大酋长 下面简单列举一下大家学习java的一个系统知识点的一些介绍 一.java基础部分:java基础的时候,有些知识点是非常重要 ...

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

    转载: 浅谈Java中的深拷贝和浅拷贝 假如说你想复制一个简单变量.很简单: int apples = 5; int pears = apples; 不仅仅是int类型,其它七种原始数据类型(bool ...

  8. 【转】浅谈Java中的hashcode方法(这个demo可以多看看)

    浅谈Java中的hashcode方法 哈希表这个数据结构想必大多数人都不陌生,而且在很多地方都会利用到hash表来提高查找效率.在Java的Object类中有一个方法: public native i ...

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

    继续上一篇浅谈java类集框架和数据结构(1)的内容 上一篇博文简介了java类集框架几大常见集合框架,这一篇博文主要分析一些接口特性以及性能优化. 一:List接口 List是最常见的数据结构了,主 ...

随机推荐

  1. 深入浅出TCP之半关闭与CLOSE_WAIT

    转自:https://www.2cto.com/net/201309/243585.html(相关链接) 深入浅出TCP之半关闭与CLOSE_WAIT 终止一个连接要经过4次握手.这由TCP的半关闭( ...

  2. Nginx启动错误:error while loading shared libraries: libpcre.so.0

    今天测试的时候,启动一个其他机器预编译好的nginx到目标测试机器(OEL 7.4)启动的时候,报了下列错误: /usr/local/nginx/sbin/nginx: error while loa ...

  3. [J2EE]struts+ejb笔记

    DispatchAtion: - org.apache.struts.actions.DispatchAction 这个类是个抽象类,但实现父类Action的execute方法,在项目中重写这个类可以 ...

  4. host文件的作用

    什么是host文件 Hosts是一个没有扩展名的系统文件,其基本作用就是将一些常用的网址域名与其对应的IP地址建立一个关联“数据库”,当用户在浏览器中输入一个需要登录的网址时,系统会首先自动从Host ...

  5. Codeforces 995F Cowmpany Cowmpensation - 组合数学

    题目传送门 传送点I 传送点II 传送点III 题目大意 给定一个棵$n$个点的有根树和整数$D$,给这$n$个点标号,要求每个节点的标号是正整数,且不超过父节点的标号,根节点的标号不得超过D. 很容 ...

  6. Mac10.13 telnet不能用的解决方法

    telnet在Mac 10.13上不能用了 Restore的方法 brew install inetutils To be clear, brew install inetutils will ins ...

  7. mysql安装方式

    1.进入mysql官网https://www.mysql.com/,选择downloads——community——mysql community server,然后在下面选择版本后点击downloa ...

  8. How to Rerun Failed Tests in JUnit?

    该帖转自其他出处 Sometimes due to some temporarily problems such as connection problems, server problems, br ...

  9. Python3基础 list list()生成空列表

             Python : 3.7.0          OS : Ubuntu 18.04.1 LTS         IDE : PyCharm 2018.2.4       Conda ...

  10. 从0开始安装fedora23的笔记-- 以及使用fedora的常规问题-2

    在shell中, 你是可以连续输入多个语句的, 中间用分号; 连接 也可以把这些多个语句放到一个函数中, 函数的话,便于多次引用. 而且 "封装" 为函数后, 可以用set查看到这 ...