Java实现生产者消费者
方法1:最简单--利用LinkedBlockingQueue
队列具有先进先出的特点,成为经常应用于生产-消费者模式的数据结构。
1.将一个对象放到队列尾部,如果队列已满,就等待直到有空闲节点。 ——put()方法
2.从队列头部取一个对象,如果没有对象,就等待直到有对象可取。 ——take()方法
3.在存取队列的过程中,锁定队列对象,不允许其它线程访问队列。——使得它是线程安全的
下面的代码适用于多个生产者、多个消费者。
//Producer.java
import java.util.concurrent.BlockingQueue; /*
* Usage example, based on a typical producer-consumer scenario.
* Note that a <tt>BlockingQueue</tt> can safely be used with multiple
* producers and multiple consumers.
* <pre>
*/
class Producer implements Runnable {
private BlockingQueue<Object> queue; Producer(BlockingQueue<Object> q) {
queue = q;
} public void run() {
try {
while (true) {
queue.put(produce());
Thread.sleep(1);
System.out.println("+1 Produce an Object:" + "生产者size:"
+ queue.size());
}
} catch (InterruptedException ex) {
System.out.println("生产者结束!");
}
} Object produce() {
return new Object();
}
}
Pruducer.java
//Consumer.java
import java.util.concurrent.BlockingQueue; class Consumer implements Runnable {
private BlockingQueue<Object> queue; Consumer(BlockingQueue<Object> q) {
queue = q;
} public void run() {
try {
while (true) {
consume(queue.take());
Thread.sleep(10);
System.out.println("-1 Consumer an Object:" + "size:"+ queue.size());
}
} catch (InterruptedException ex) {
System.out.println("消费者结束!");
}
} void consume(Object x) {
}
}
Consumer.java
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue; class Main {
public static void main(String[] args) {
BlockingQueue<Object> q = new LinkedBlockingQueue<Object>();// SomeQueueImplementation();
Producer p = new Producer(q);
Consumer c1 = new Consumer(q);
Consumer c2 = new Consumer(q);
Thread pth = new Thread(p);
pth.start();
new Thread(c1).start();
new Thread(c2).start();
try {
Thread.sleep(50);
pth.interrupt();
} catch (InterruptedException e) {
}
}
}
Main.java
方法2:不采用BlockingQueue,利用lock、Condition来实现
思路:
利用可重用的LinkedList来存放资源,生产者addLast(),消费者removeFirst()。
使用ReentrantLock()来实现消费者和生产者的同步;//可重用的互斥锁
思考:为什么使用了lock后,还使用了它的2个newCondition,这样做有什么好处?
import java.util.*;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; public class ProducerConsumer {
private static final LinkedList<Integer> buffer = new LinkedList<Integer>();
private static final int BUFFERSIZE = 10;
private static Lock lock = new ReentrantLock();//可重用的互斥锁
private static Condition NotFull = lock.newCondition();
private static Condition NotEmpty = lock.newCondition(); static class Producer extends Thread {
public void run() {
while (true) {
// lock
lock.lock();
if (buffer.size() == BUFFERSIZE) {
System.out.println("BUffer is fulls");
try {
NotFull.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
buffer.addLast(1);
NotEmpty.signal();
}
lock.unlock();
// unlock
}
}
} static class Consumer extends Thread {
public void run() {
while (true) {
// lock
lock.lock();
if (buffer.size() == 0) {
System.out.println("BUffer is empty");
try {
NotEmpty.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
buffer.removeFirst();
NotFull.signal();
}
// unlock
lock.unlock();
}
}
} public static void main(String[] args){
new Consumer().start();
new Producer().start();
}
}
ProducerConsumer .java
关于Java线程的lock、condition、synchronized的小小总结:
1.synchronized简单易用,但是功能受局限,无法满足复杂的同步机制,比如“读者写者问题”:多个读者线程是不互斥的。
2.lock以更优雅的方式来解决线程同步,比如读写锁ReadWriteLock。
3.Condition解决线程间通信,为不同的线程建立不同的条件。
推荐博文:Java线程-锁机制
Condition可以替代传统的线程间通信,用await()替换wait(),用signal()替换notify(),用signalAll()替换notifyAll()。
——为什么方法名不直接叫wait()/notify()/nofityAll()?因为Object的这几个方法是final的,不可重写!
Condition实现了BlockingQueue的功能。
看看BlockingQueue的继承和实现。

一般的锁Lock的实现:注意ReadLock、WriteLock是内部的静态类,只有ReentrantReadWriteLock类可以调用。

读写的锁ReadWriteLock

思考:OS的信号量是什么,线程通信的方式有哪些?共享变量和消息传递。
信号量与互斥锁有什么联系?
By BYRHuangQiang2014-03-18 09:05:30
Java实现生产者消费者的更多相关文章
- Java实现生产者消费者问题与读者写者问题
摘要: Java实现生产者消费者问题与读者写者问题 1.生产者消费者问题 生产者消费者问题是研究多线程程序时绕不开的经典问题之一,它描述是有一块缓冲区作为仓库,生产者可以将产品放入仓库,消费者则可以从 ...
- Java设计模式—生产者消费者模式(阻塞队列实现)
生产者消费者模式是并发.多线程编程中经典的设计模式,生产者和消费者通过分离的执行工作解耦,简化了开发模式,生产者和消费者可以以不同的速度生产和消费数据.这篇文章我们来看看什么是生产者消费者模式,这个问 ...
- java实现生产者消费者问题
引言 生产者和消费者问题是线程模型中的经典问题:生产者和消费者在同一时间段内共用同一个存储空间,如下图所示,生产者向空间里存放数据,而消费者取用数据,如果不加以协调可能会出现以下情况: 生产者消费者图 ...
- java实现生产者消费者问题(转)
引言 生产者和消费者问题是线程模型中的经典问题:生产者和消费者在同一时间段内共用同一个存储空间,如下图所示,生产者向空间里存放数据,而消费者取用数据,如果不加以协调可能会出现以下情况: 生产者消费者图 ...
- [转载] Java实现生产者消费者问题
转载自http://www.cnblogs.com/happyPawpaw/archive/2013/01/18/2865957.html 引言 生产者和消费者问题是线程模型中的经典问题:生产者和消费 ...
- java实现生产者消费者模式
生产者消费者问题是一个著名的线程同步问题,该问题描述如下:有一个生产者在生产产品,这些产品将提供给若干个消费者去消费,为了使生产者和消费者能并发执行,在两者之间设置一个具有多个缓冲区的缓冲池,生产者将 ...
- java 线程 生产者-消费者与队列,任务间使用管道进行输入、输出 解说演示样例 --thinking java4
package org.rui.thread.block2; import java.io.BufferedReader; import java.io.IOException; import jav ...
- Java 实现生产者 – 消费者模型
转自:http://www.importnew.com/27063.html 考查Java的并发编程时,手写“生产者-消费者模型”是一个经典问题.有如下几个考点: 对Java并发模型的理解 对Java ...
- Java——Java实现生产者消费者
1.生产/消费者模型 生产/消费者问题是个非常典型的多线程问题,涉及到的对象包括"生产者"."消费者"."仓库"和"产品" ...
- java多线程 生产者消费者模式
package de.bvb; /** * 生产者消费者模式 * 通过 wait() 和 notify() 通信方法实现 * */ public class Test1 { public static ...
随机推荐
- android之listView定位到指定行同时隐藏输入键盘
帮别人该bug遇到的一个问题,记录下来. listView.setSelection(a); 这个方法可以让让你的listview定位到指定行 但是如果紧接着执行隐藏输入键盘的代码,则会有bug,这个 ...
- minicom移植到ARM开发平台
minicom需要ncurses库的支持.arm-linux-gcc中并没有此库故需要交叉编译ncurses,否则出现很多头文件.库函数找不到. 软件环境: ncurses-6.0 下载网址:http ...
- Spring各种传播特性源码实现的概览
这几天都在分析Spring的源码实现,看到事务管理的部分 我们知道事务的传播特性有下面几种,我标黄的就是最常用的3中传播特性, Sping在发生事务嵌套的时候,会依据内层事务的传播特性,来决定内层是事 ...
- .NET设计模式(8):适配器模式(Adapter Pattern)
):适配器模式(Adapter Pattern) 适配器模式(Adapter Pattern) --.NET设计模式系列之八 Terrylee,2006年2月 概述 在软件系统中,由于应用环境的 ...
- 《你不常用的c#之一》:略谈unsafe
转自csdn:http://blog.csdn.net/robingaoxb/article/details/6199508 msdn里讲到: “在 C# 中很少需要使用指针,但仍有一些需要使用的情况 ...
- 隐藏TabBar的一些方法小结(适用与各种情况)
在项目中经常遇到隐藏tabBar,实力很多种方法,可以解决不同情况下问题 使用中涉及到view的层次关系,下面的使用方法 1.2不做说明:在使用3.4方法时注意要在tabBar所在的rootView中 ...
- ASP.NET Web API教程(六) 安全与身份认证
在实际的项目应用中,很多时候都需要保证数据的安全和可靠,如何来保证数据的安全呢?做法有很多,最常见的就是进行身份验证.验证通过,根据验证过的身份给与对应访问权限.同在Web Api中如何实现身份认证呢 ...
- CSS 链接
不同的链接可以有不同的样式. 链接样式 链接的样式,可以用任何CSS属性(如颜色,字体,背景等). 特别的链接,可以有不同的样式,这取决于他们是什么状态. 这四个链接状态是: a:link - 正常, ...
- js操作数据库实现注册和登陆
自从node-js出现之后,不只是java,php等后端语言可以操作数据库,进行内容的增删改查,javascript简本语言同样具备了该项技能,而且在node下,js具备了很强的操作性和代码的阅读性, ...
- ubuntu npm 私有库搭建 (npmjs.org 官方版本)
目标 npm.xxx.com 安装和推送nodejs包 npmui.xxx.com 管理已经推送的nodejs包 安装 couchdb https://launchpad.net/~couch ...