转载自http://www.cnblogs.com/happyPawpaw/archive/2013/01/18/2865957.html

引言

  生产者和消费者问题是线程模型中的经典问题:生产者和消费者在同一时间内共用同一个存储空间,如下图所示,生产者向空间里存放数据,而消费者取用数据,如果不加以协调可能会出现以下情况:

生产者消费者图

  存储空间已满,而生产者占用着它,消费者等着生产者让出空间从而去除产品,生产者等着消费者消费产品,从而向空间中添加产品。互相等待,从而发生死锁。

JAVA解决线程模型的三种方式

  1、wait()和notify()

import java.util.LinkedList;

public class ProducerConsumer {
private LinkedList<Object> storeHouse = new LinkedList<Object>();
private int MAX = 10; public ProducerConsumer() {
} public void start() {
new Producer().start();
new Comsumer().start();
} class Producer extends Thread {
public void run() {
while (true) {
synchronized (storeHouse) {
try {
while (storeHouse.size() == MAX) {
System.out.println("storeHouse is full , please wait");
storeHouse.wait();
}
Object newOb = new Object();
if (storeHouse.add(newOb)) {
System.out.println("Producer put a Object to storeHouse");
Thread.sleep((long) (Math.random() * 3000));
storeHouse.notify();
}
} catch (InterruptedException ie) {
System.out.println("producer is interrupted!");
} }
}
}
} class Comsumer extends Thread {
public void run() {
while (true) {
synchronized (storeHouse) {
try {
while (storeHouse.size() == 0) {
System.out.println("storeHouse is empty , please wait");
storeHouse.wait();
}
storeHouse.removeLast();
System.out.println("Comsumer get a Object from storeHouse");
Thread.sleep((long) (Math.random() * 3000));
storeHouse.notify();
} catch (InterruptedException ie) {
System.out.println("Consumer is interrupted");
} }
} }
} public static void main(String[] args) throws Exception {
ProducerConsumer pc = new ProducerConsumer();
pc.start();
}
}

  2、await()和signal(),即线程锁的方式

package sort;

import java.util.LinkedList;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; public class ProducerConsumer {
private LinkedList<Object> myList = new LinkedList<Object>();
private int MAX = 10;
private final Lock lock = new ReentrantLock();
private final Condition full = lock.newCondition();
private final Condition empty = lock.newCondition(); public ProducerConsumer() {
} public void start() {
new Producer().start();
new Consumer().start();
} public static void main(String[] args) throws Exception {
ProducerConsumer s2 = new ProducerConsumer();
s2.start();
} class Producer extends Thread {
public void run() {
while (true) {
lock.lock();
try {
while (myList.size() == MAX) {
System.out.println("warning: it's full!");
full.await();
}
Object o = new Object();
if (myList.add(o)) {
System.out.println("Producer: " + o);
empty.signal();
}
} catch (InterruptedException ie) {
System.out.println("producer is interrupted!");
} finally {
lock.unlock();
}
}
}
} class Consumer extends Thread {
public void run() {
while (true) {
lock.lock();
try {
while (myList.size() == 0) {
System.out.println("warning: it's empty!");
empty.await();
}
Object o = myList.removeLast();
System.out.println("Consumer: " + o);
full.signal();
} catch (InterruptedException ie) {
System.out.println("consumer is interrupted!");
} finally {
lock.unlock();
}
}
}
} }

  3、阻塞队列的方式

import java.util.concurrent.*;

public class ProducerConsumer {
// 建立一个阻塞队列
private LinkedBlockingQueue<Object> queue = new LinkedBlockingQueue<Object>(10); public ProducerConsumer() {
} public void start() {
new Producer().start();
new Consumer().start();
} public static void main(String[] args) throws Exception {
ProducerConsumer s3 = new ProducerConsumer();
s3.start();
} class Producer extends Thread {
public void run() {
while (true) {
try {
Object o = new Object();
// 取出一个对象
queue.put(o);
System.out.println("Producer: " + o);
} catch (InterruptedException e) {
System.out.println("producer is interrupted!");
}
// }
}
}
} class Consumer extends Thread {
public void run() {
while (true) {
try {
// 取出一个对象
Object o = queue.take();
System.out.println("Consumer: " + o);
} catch (InterruptedException e) {
System.out.println("producer is interrupted!");
}
// }
}
}
} }

结论

  三种方式原理一致,都是对独占空间加锁,阻塞和唤醒线程,第一种方式比较传统,第三种方式最简单,只需存储和取用,线程同步的操作交由LinkedBlockingQueue全权处理。

[转载] Java实现生产者消费者问题的更多相关文章

  1. Java实现生产者消费者问题与读者写者问题

    摘要: Java实现生产者消费者问题与读者写者问题 1.生产者消费者问题 生产者消费者问题是研究多线程程序时绕不开的经典问题之一,它描述是有一块缓冲区作为仓库,生产者可以将产品放入仓库,消费者则可以从 ...

  2. Java设计模式—生产者消费者模式(阻塞队列实现)

    生产者消费者模式是并发.多线程编程中经典的设计模式,生产者和消费者通过分离的执行工作解耦,简化了开发模式,生产者和消费者可以以不同的速度生产和消费数据.这篇文章我们来看看什么是生产者消费者模式,这个问 ...

  3. java实现生产者消费者问题

    引言 生产者和消费者问题是线程模型中的经典问题:生产者和消费者在同一时间段内共用同一个存储空间,如下图所示,生产者向空间里存放数据,而消费者取用数据,如果不加以协调可能会出现以下情况: 生产者消费者图 ...

  4. java实现生产者消费者问题(转)

    引言 生产者和消费者问题是线程模型中的经典问题:生产者和消费者在同一时间段内共用同一个存储空间,如下图所示,生产者向空间里存放数据,而消费者取用数据,如果不加以协调可能会出现以下情况: 生产者消费者图 ...

  5. java实现生产者消费者模式

    生产者消费者问题是一个著名的线程同步问题,该问题描述如下:有一个生产者在生产产品,这些产品将提供给若干个消费者去消费,为了使生产者和消费者能并发执行,在两者之间设置一个具有多个缓冲区的缓冲池,生产者将 ...

  6. java 线程 生产者-消费者与队列,任务间使用管道进行输入、输出 解说演示样例 --thinking java4

    package org.rui.thread.block2; import java.io.BufferedReader; import java.io.IOException; import jav ...

  7. Java 实现生产者 – 消费者模型

    转自:http://www.importnew.com/27063.html 考查Java的并发编程时,手写“生产者-消费者模型”是一个经典问题.有如下几个考点: 对Java并发模型的理解 对Java ...

  8. Java——Java实现生产者消费者

    1.生产/消费者模型 生产/消费者问题是个非常典型的多线程问题,涉及到的对象包括"生产者"."消费者"."仓库"和"产品" ...

  9. java多线程 生产者消费者模式

    package de.bvb; /** * 生产者消费者模式 * 通过 wait() 和 notify() 通信方法实现 * */ public class Test1 { public static ...

随机推荐

  1. git-分支使用方式

    需求场景:假如你看着教程完成了一个项目,但是感觉第一次代码掌握不牢,想要进行第二次代码练习--如果某某心里想我还有初始备份文件,我此时的心里独白是你的硬盘还够用吗o(╯□╰)o 1 创建一个新分支 - ...

  2. Vue与swiper想结合封装全屏轮播插件

    项目需求介绍: 1.页面图文混排, 2.点击图片后全屏展示图片,并在底部显示文字,如果没有则不显示 3.关闭全屏后依然停留在上次浏览的位置 4.浏览图片时,不管点击的哪张图片,全屏展示的时候也要显示这 ...

  3. PPLB条码打印

    using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...

  4. BaseServlet,让一个servlet处理多个请求

    BaseServlet 第一次学习servlet的时候是跟着传智播客免费的教学视频,其中崔希凡讲的是我学过自认讲的最好的一位,BaseServlet也是跟着他写过一次,当时很多东西不能理解,后来慢慢发 ...

  5. Echarts数据可视化地理坐标系geo,开发全解+完美注释

    全栈工程师开发手册 (作者:栾鹏) Echarts数据可视化开发代码注释全解 Echarts数据可视化开发参数配置全解 6大公共组件详解(点击进入): title详解. tooltip详解.toolb ...

  6. 【特效】单选按钮和复选框的美化(只用css)

    表单的默认样式都是比较朴素的,实际页面中往往需要美化他们.这里先说说单选按钮和复选框,有了css3,这个问题就变的好解决了.利用input与label相关联,对label进行美化并使其覆盖掉原本的in ...

  7. vue-cli 自定义指令directive 添加验证滑块

    vue项目注册登录页面遇到了一个需要滑块的功能,网上看了很多插件发现都不太好用,于是自己写了一个插件供大家参考: 用的是vue的自定义指令direcive,只需要在需要的组件里放入对应的标签嵌套即可: ...

  8. win10 uwp 通知Toast

    win10通知使用Toast 可以使用win10 模板添加通知 var t = Windows.UI.Notifications.ToastTemplateType.ToastText02; 使用Ge ...

  9. springcloud之服务注册与发现(Eureka)

    springcloud服务注册与发现 使用Eureka实现服务治理 作用:实现服务治理(服务注册与发现) 简介: Spring Cloud Eureka是Spring Cloud Netflix项目下 ...

  10. 详解变量声明加 var 和不加 var 的区别

    在全局作用域中声明变量加 var 关键字和不加 var ,js 引擎都会将这个变量声明为全局变量,在实际运行时,两种声明方式的变量的行为也是几乎一致的.但是在全局作用域下是否声明一个变量的 时候加va ...