我的技术博客经常被流氓网站恶意爬取转载。请移步原文:http://www.cnblogs.com/hamhog/p/3555111.html,享受整齐的排版、有效的链接、正确的代码缩进、更好的阅读体验。

【实现1:synchronized】

含测试函数main。

public class ProductManagerUsingSync {

    static final int MAX_AMOUNT = 1000;
int currentAmount; /**
* @param args
*/
public static void main(String[] args) {
ProductManagerUsingSync manager = new ProductManagerUsingSync(); for (int i = 0; i < 5; i++){
int consume = (int) Math.round(Math.random()*50) + 10;
Thread consumerThread = new Thread(new ConsumerWithSync(consume, manager));
consumerThread.start();
} for (int i = 0; i < 10; i++){
int produce = (int) Math.round(Math.random()*50) + 10;
Thread producerThread = new Thread(new ProducerWithSync(produce, manager));
producerThread.start();
}
} public ProductManagerUsingSync() {
currentAmount = 0;
} /**
* Add product. If can't, return.
* @param addAmount
* @return if succeeded.
*/
public boolean addProduct(int addAmount){
if (currentAmount + addAmount > MAX_AMOUNT)
return false; currentAmount += addAmount;
System.out.println("produced: " + addAmount + " current: " + currentAmount);
return true;
} /**
* Take product. If can't, return.
* @param takeAmount The amount of product to take.
* @return if succeeded.
*/
public boolean takeProduct(int takeAmount){
if (takeAmount > currentAmount)
return false; currentAmount -= takeAmount;
System.out.println("consumed: " + takeAmount + " current: " + currentAmount);
return true;
} } class ProducerWithSync implements Runnable {
private int amount;
private ProductManagerUsingSync manager; ProducerWithSync(int amount, ProductManagerUsingSync manager) {
this.amount = amount;
this.manager = manager;
} @Override
public void run() {
while (true) {
synchronized (manager) {
if (manager.addProduct(amount))
return;
}
}
}
} class ConsumerWithSync implements Runnable {
private int amount;
private ProductManagerUsingSync manager; ConsumerWithSync(int amount, ProductManagerUsingSync manager) {
this.amount = amount;
this.manager = manager;
} @Override
public void run() {
while (true) {
synchronized (manager) {
if (manager.takeProduct(amount))
return;
}
}
}
}

解释:Consumer类和Producer类在run方法中进行产品的生产和消费。重点在于:1. 在尝试生产、消费前会获取manager上的锁。由于所有的生产者、消费者中的manager都是同一个实例,因此消费、生产过程是保证线程安全(单线程串行)的。2. 在生产、消费失败的情况下,会进入死循环,反复再次尝试,直到成功为止。

这种实现方法下,暂时不能生产、消费时需要一直死循环,太占资源了;如果在每次循环之间sleep,则不一定能及时生产、消费。

【实现2:signal/notifyAll】

含测试函数main。

public class ProductManagerUsingSignal {

    static final int MAX_AMOUNT = 1000;
int currentAmount; /**
* @param args useless
*/
public static void main(String[] args) {
ProductManagerUsingSignal manager = new ProductManagerUsingSignal(); for (int i = 0; i < 5; i++){
int consume = (int) Math.round(Math.random()*50);
Thread consumerThread = new Thread(new Consumer(consume, manager));
consumerThread.start();
} for (int i = 0; i < 10; i++){
int produce = (int) Math.round(Math.random()*50);
Thread producerThread = new Thread(new Producer(produce, manager));
producerThread.start();
}
} public ProductManagerUsingSignal(){
currentAmount = 0;
} /**
* Add product. If can't, wait. NotifyAll when finished.
* @param addAmount The amount of product to add.
*/
public synchronized void addProduct(int addAmount){
while (currentAmount + addAmount > MAX_AMOUNT) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
currentAmount += addAmount;
System.out.println("produced: " + addAmount + " current: " + currentAmount);
notifyAll();
} /**
* Take product. If can't, wait. NotifyAll when finished.
* @param takeAmount The amount of product to take.
*/
public synchronized void takeProduct(int takeAmount){
while (takeAmount > currentAmount) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
currentAmount -= takeAmount;
System.out.println("consumed: " + takeAmount + " current: " + currentAmount);
notifyAll();
} } class Producer implements Runnable {
private int amount;
private ProductManagerUsingSignal manager; Producer(int amount, ProductManagerUsingSignal manager) {
this.amount = amount;
this.manager = manager;
} @Override
public void run() {
manager.addProduct(amount);
}
} class Consumer implements Runnable {
private int amount;
private ProductManagerUsingSignal manager; Consumer(int amount, ProductManagerUsingSignal manager) {
this.amount = amount;
this.manager = manager;
} @Override
public void run() {
manager.takeProduct(amount);
}
}

解释:这种实现同样用synchronized保证线程安全;它的重点在于,当生产、消费失败时,会进入wait状态,让位给其他线程;而完成一次成功的生产或消费后,会调用notifyAll方法,唤醒之前等待状态的进程。这种实现在效率上要好于第一种。

【实现3:BlockingQueue】

含测试函数main。

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue; public class ProductManagerUsingBlockingQueue { BlockingQueue<Integer> sharedQueue;
/**
* @param args
*/
public static void main(String[] args) {
sharedQueue = new LinkedBlockingQueue<Integer>(); for (int i = 0; i < 10; i++){
Thread consumerThread = new Thread(new ConsumerWithBlockingQueue(sharedQueue));
consumerThread.start();
} for (int i = 0; i < 10; i++){
Thread producerThread = new Thread(new ProducerWithBlockingQueue(i, sharedQueue));
producerThread.start();
}
} } class ProducerWithBlockingQueue implements Runnable { private int amount;
private final BlockingQueue<Integer> sharedQueue; public ProducerWithBlockingQueue (int amount, BlockingQueue<Integer> sharedQueue) {
this.amount = amount;
this.sharedQueue = sharedQueue;
} @Override
public void run() { try {
sharedQueue.put(amount);
System.out.println("produced: " + amount);
} catch (InterruptedException e) {
e.printStackTrace();
}
} } class ConsumerWithBlockingQueue implements Runnable{ private final BlockingQueue<Integer> sharedQueue; public ConsumerWithBlockingQueue (BlockingQueue<Integer> sharedQueue) {
this.sharedQueue = sharedQueue;
} @Override
public void run() {
try {
System.out.println("consumed: " + sharedQueue.take());
} catch (InterruptedException e) {
e.printStackTrace();
}
} }

解释:这种方法借助数据结构BlockingQueue(初始化好像应该放在构造函数里,暂时来不及改了),底层原理与signal/notifyAll类似,但代码实现就简洁了许多。

【总结】

在需要实现生产者-消费者模式的场景下,我们可以优先考虑用BlockingQueue来实现。

生产者-消费者模型的3种Java实现:synchronized,signal/notifyAll及BlockingQueue的更多相关文章

  1. java多线程:线程间通信——生产者消费者模型

    一.背景 && 定义 多线程环境下,只要有并发问题,就要保证数据的安全性,一般指的是通过 synchronized 来进行同步. 另一个问题是,多个线程之间如何协作呢? 我们看一个仓库 ...

  2. 结合生活,剖析《生产者消费者模型》-java多线程(一)

    博客园的园友们好,看博客园上各位大佬的文章,已陪伴了我程序员职业的三年, 如今自己同样希望能把自己从小白到菜鸟的成长过程分享给大家.不定期更新!!! 首先我本人智商不高,理解问题十分吃力,完全不属于天 ...

  3. 【1】【JUC】Condition和生产者消费者模型

    本篇文章将介绍Condition的实现原理和基本使用方法,基本过程如下: 1.Condition提供了await()方法将当前线程阻塞,并提供signal()方法支持另外一个线程将已经阻塞的线程唤醒. ...

  4. Java里的生产者-消费者模型(Producer and Consumer Pattern in Java)

    生产者-消费者模型是多线程问题里面的经典问题,也是面试的常见问题.有如下几个常见的实现方法: 1. wait()/notify() 2. lock & condition 3. Blockin ...

  5. Java多线程15:Queue、BlockingQueue以及利用BlockingQueue实现生产者/消费者模型

    Queue是什么 队列,是一种数据结构.除了优先级队列和LIFO队列外,队列都是以FIFO(先进先出)的方式对各个元素进行排序的.无论使用哪种排序方式,队列的头都是调用remove()或poll()移 ...

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

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

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

    生产者消费者模型 生产者消费者模型可以描述为: ①生产者持续生产,直到仓库放满产品,则停止生产进入等待状态:仓库不满后继续生产: ②消费者持续消费,直到仓库空,则停止消费进入等待状态:仓库不空后,继续 ...

  8. 第23章 java线程通信——生产者/消费者模型案例

    第23章 java线程通信--生产者/消费者模型案例 1.案例: package com.rocco; /** * 生产者消费者问题,涉及到几个类 * 第一,这个问题本身就是一个类,即主类 * 第二, ...

  9. Java多线程14:生产者/消费者模型

    什么是生产者/消费者模型 一种重要的模型,基于等待/通知机制.生产者/消费者模型描述的是有一块缓冲区作为仓库,生产者可将产品放入仓库,消费者可以从仓库中取出产品,生产者/消费者模型关注的是以下几个点: ...

随机推荐

  1. Ant-常用命令(笔记二)

    1.copy命令: <?xml version="1.0" encoding="utf-8"?> <project name="co ...

  2. JAVA线程全局异常处理

    大家平时写线程很多,但可能很少关注如何捕获线程的全局异常.其实jdk提供了两种捕获全局异常的方法,一种是基于整个线程类(staticsetDefaultUnaughtExceptionHandler( ...

  3. 在artTemplate的标签中使用外部函数的方法

    第一步,声明函数,并将函数作为data对象的属性.例如: var resArray = new Array(); function beforeRender(data) { //addToArray为 ...

  4. android学习日记08--Paint画笔

    Paint 要绘图,首先得调整画笔,待画笔调整好之后,再将图像绘制到画布Canvas上,这样才可以显示在手机屏幕上.Android 中的画笔是 Paint类,Paint 中包含了很多方法对其属性进行设 ...

  5. UIWebView的使用,简单浏览器的实现

    #import "ViewController.h" @interface ViewController () <UIWebViewDelegate> @propert ...

  6. WebStorm 6.0下运行pomelo项目

    最近想使用WebStorm来写pomelo,初次使用WebStorm,网上找了老半天根本没有介绍WebStorm如何创建或者打开运行pomelo的教程,网易pomelo官网介绍的使用 WebStorm ...

  7. 生产者/消费者问题的多种Java实现方式--转

    实质上,很多后台服务程序并发控制的基本原理都可以归纳为生产者/消费者模式,而这是恰恰是在本科操作系统课堂上老师反复讲解,而我们却视而不见不以为然的.在博文<一种面向作业流(工作流)的轻量级可复用 ...

  8. vb.net写的odbc连接dsn数据源和ole链接oracle的小例子

    最近由于工作需要开始接触vb2010,也叫vb.net.相比vb6.0有面向对象编程的优势.同时接触一门新语言,要更快的实际应用起来,链接数据库是必不可少的.之前用vba写过一个售书工具,正好可以拿来 ...

  9. 简单的jquery选择器的实现

    function getByClass(oParent,oClass){    if(document.getElementsByClassName){         return document ...

  10. FIFO分枝_限界算法

    问题: 检索4-皇后问题的状态空间树如下图的基本过程.(4-皇后问题解空间的树结构,结点按深度优先检索编号)  如果按序扩展这些结点,则下一个E-结点就是结点2.扩展结点2后生成结点3,8和13.利用 ...