文档章节

Java 多线程——生产者与消费者

雨中人X
 雨中人X
发布于 2016/12/11 15:50
字数 854
阅读 29
收藏 2
点赞 0
评论 0

Java 多线程——生产者与消费者

生产者消费者问题是一个典型的线程同步问题,需要满足以下条件

  1. 生产者将物品放置到一个队列中,消费者按顺序取走
  2. 当队列满时,生产者需要停止生产,当队列为空时,消费者只能等待
  3. 当生产者向队列中加入产品时,需要通知消费者。当消费者取走物品时,需要通知生产者

原理

  • 入队操作
synchronized(this){
    while(!cond){
        wait()    
    }
    add(e)
    notifyAll()
}
  • 出队操作
synchronized(this){
    while(!cond){
        wait()    
    }
   poll()
   notifyAll()
}

注:此处的判断条件不能使用if,避免线程被唤醒时不满足条件。故线程被唤醒后需要 再次检查条件,看是否满足条件。当存在多个消费者线程和生产者线程时,线程被唤醒时 就可能不满足条件。读者可以自己尝试,多个消费者和生产者时使用if进行判断,会出现什么现象

Java实现

下面看一下Java代码实现

Factory.java 使用了Java的ArrayDeque 实现同步队列

package com.hive;

import java.util.ArrayDeque;
import java.util.Queue;

/**
 * Created by albert on 16-12-11.
 */
public class Factory {
    private final static int MAX_SIZE = 10;
    private Queue<String> pool;

    public Factory() {
        pool = new ArrayDeque<>();
    }

    synchronized public String poll() {
        while (pool.size() == 0) {    // 此处不应用 if判断,避免被错误唤醒
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        notifyAll(); // 通知生产者线程
        return pool.poll();
    }

    synchronized public void add(String e) {
        while (pool.size() > MAX_SIZE) {   // 此处不应用 if判断,避免被错误唤醒
            try {
                wait();
            } catch (InterruptedException e1) {
                e1.printStackTrace();
            }
        }
        pool.add(e);
        notifyAll(); // 通知消费者线程
    }
}

Producer.java 生产者类

package com.hive;

import java.lang.String;

/**
 * Created by albert on 16-12-11.
 */
public class Producer implements Runnable {
    private String name;
    private Factory goods;

    public Producer(String name, Factory goods) {
        this.name = name;
        this.goods = goods;
    }


    @Override
    public void run() {
        while (true) {
            for (int i = 0; i < 20; i++) {
                System.out.println(name + " yield " + i);
                goods.add(name + ">" + i);
                try {
                    Thread.sleep(1 * 100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

Customer.java 消费者类

package com.hive;

/**
 * Created by albert on 16-12-11.
 */
public class Customer implements Runnable {
    private String name;
    private Factory goods;

    public Customer(String name, Factory goods) {
        this.name = name;
        this.goods = goods;
    }

    @Override
    public void run() {
        while (true) {
            System.out.println(name + " use " + goods.poll());
            try {
                Thread.sleep(10 * 100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

Main.java 测试方法

package com.hive;

public class Main {

    public static void main(String[] args) {
        Factory goods = new Factory();
        Producer p1 = new Producer("P1", goods);
        Producer p2 = new Producer("P2", goods);
        Customer c1 = new Customer("C1", goods);
        Customer c2 = new Customer("C2", goods);
        new Thread(p1).start();
        new Thread(p2).start();
        new Thread(c1).start();
        new Thread(c2).start();
    }
}

## 运行结果

P1 yield 0
P2 yield 0
C1 use P1>0
C2 use P2>0
P1 yield 1
P2 yield 1
P1 yield 2
P2 yield 2
P1 yield 3
P2 yield 3
P1 yield 4
P2 yield 4
P1 yield 5
P2 yield 5
P1 yield 6
P2 yield 6
P2 yield 7
C1 use P1>1
C2 use P2>1
P2 yield 8
P1 yield 7
C1 use P1>2
C2 use P2>2
P1 yield 8
P2 yield 9
C1 use P1>3
C2 use P2>3
P2 yield 10
P1 yield 9
C2 use P2>4
C1 use P1>4
P1 yield 10
P2 yield 11
C2 use P1>5
C1 use P2>5
P1 yield 11
P2 yield 12
C2 use P2>6
C1 use P2>7
P1 yield 12
P2 yield 13
C2 use P1>6
C1 use P1>7
P2 yield 14
P1 yield 13
C2 use P2>8
C1 use P2>9

© 著作权归作者所有

共有 人打赏支持
雨中人X
粉丝 7
博文 57
码字总数 15326
作品 0
深圳
高级程序员
【转】15个顶级Java多线程面试题及回答

Java 线程面试问题   在任何Java面试当中多线程和并发方面的问题都是必不可少的一部分。如果你想获得任何股票投资银行的前台资讯职位,那么你应该准备很多关于多线程的问题。在投资银行业务...

一只死笨死笨的猪
2014/09/30
0
0
Java多线程生产者消费者实例

Java生产者消费者实例 设计:涉及到的类有食物、厨师、服务员、顾客以及测试类。厨师负责生产食物,服务员服务于顾客,顾客负责点餐以及吃饭。 技术点:Java多线程,线程安全(synchronized),...

cicadaT
2017/11/05
0
1
15个顶级Java多线程面试题及回答

Java 线程面试问题 在任何Java面试当中多线程和并发方面的问题都是必不可少的一部分。如果你想获得任何股票投资银行的前台资讯职位,那么你应该准备很多关于多线程的问题。在投资银行业务中多...

LCZ777
2014/05/27
0
0
activemq in action学习笔记

JMS基本概念 JMS 是 SUN 公司开发的一套访问 MOM(Message-Oriented-Middleware) 消息服务中间件的标准 API。 MOM 提供消息接收和转发的服务,对消息进行缓存和持久操作,保证消息的安全性,JMS让...

dyzhou
2015/08/24
0
1
Java面试需要准备哪些多线程并发的技术要点

一、概念 什么是线程 一个线程要执行任务,必须得有线程 一个进程(程序)的所有任务都在线程中执行的 一个线程执行任务是串行的,也就是说一个线程,同一时间内,只能执行一个任务 多线程原理 同一...

码蚁说架构
05/31
0
0
java基础thread——java5之后的多线程(浅尝辄止)

承上启下 虽然我们可以理解同步代码块和同步方法的锁对象问题,但是我们并没有直接看到在哪里加上了锁,在哪里释放了锁,为了更清晰的表达如何加锁和释放锁,JDK5以后提供了一个新的锁对象L...

潇潇漓燃
06/03
0
0
生产者消费者问题理解与Java实现

生产者消费者问题(英语:Producer-consumer problem),也称有限缓冲问题(英语:Bounded-buffer problem),是一个多线程同步问题的经典案例。该问题描述了两个共享固定大小缓冲区的线程—...

hanzhankang
2014/01/17
0
0
JAVA多线程和并发基础面试问答

原文链接 译文连接 作者:Pankaj 译者:郑旭东 校对:方腾飞 多线程和并发问题是Java技术面试中面试官比较喜欢问的问题之一。在这里,从面试的角度列出了大部分重要的问题,但是你仍然应该牢...

雷神雨石
2014/07/19
0
2
JAVA多线程和并发基础面试问答

多线程和并发问题是Java技术面试中面试官比较喜欢问的问题之一。在这里,从面试的角度列出了大部分重要的问题,但是你仍然应该牢固的掌握Java多线程基础知识来对应日后碰到的问题。(校对注:...

LCZ777
2014/05/26
0
0
JAVA多线程和并发基础面试问答

Java多线程面试问题 1. 进程和线程之间有什么不同? 一个进程是一个独立(self contained)的运行环境,它可以被看作一个程序或者一个应用。而线程是在进程中执行的一个任务。Java运行环境是一...

清风傲剑
2014/12/06
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

数据库事务的四大特性以及事务的隔离级别

本篇讲述数据库中事务的四大特性(ACID),并且将会详细地说明事务的隔离级别。 如果一个数据库声称支持事务的操作,那么该数据库必须要具备以下四个特性: ⑴ 原子性(Atomicity) 原子性是...

Java大蜗牛
14分钟前
0
0
Spring Boot 整合 MyBatis/通用Mapper/PageHelper分页插件

整合MyBatis 整合通用Mapper 1. POM依赖配置 <properties><mapper.starter.version>2.0.3-beta1</mapper.starter.version></properties><!-- 通用Mapper --><dependency><groupId>t......

OSC_fly
22分钟前
0
0
CentOS7 双网卡绑定

环境 操作系统 CentOS7.5,禁用 NetworkManager 服务 网卡 eth0 网卡 eth1 绑定网卡 bond0 网卡 eth0 配置 修改 /etc/sysconfig/network-scripts/ifcfg-eth0 TYPE=EthernetBOOTPROTO=noneD......

Colben
24分钟前
0
0
zk实战--rpc框架集群化

在看此篇内容时需要浏览下面内容 netty实战--手写rpc框架 前文功能简介以及功能扩充 利用netty来实现一个点对点的rpc调用。客户端和服务端都是靠手写地址进行socket同学的,无法1对多,也无法...

xpbob
40分钟前
11
0
springboot 发送邮件

获取授权码 添加配置 # 账号和密码spring.mail.username=aaa@qq.comspring.mail.password=bbb# 服务器地址spring.mail.host=smtp.qq.comspring.mail.properties.mail.smtp.ssl.en...

阿豪boy
41分钟前
0
0
如何使用GNU Ring?

文章名:如何使用GNU Ring? 作者:冰焰火灵X 1079092922@qq.com 文章许可:CC BY-SA 4.0 ##1. 安装 下载GNU Ring 点击左边选择你的系统版本(这里以 GNU/Linux 为例,我使用的是Mint 18.3)...

ICE冰焰火灵X
44分钟前
4
0
深入理解springMVC

什么是spring MVC Spring MVC属于SpringFrameWork的后续产品,已经融合在Spring Web Flow里面。Spring 框架提供了构建 Web 应用程序的全功能 MVC 模块。使用 Spring 可插入的 MVC 架构,从而...

Java填坑之路
49分钟前
1
0
《射雕英雄传》书摘

1. 我虽是个飘泊江湖的贫家女子,可不是低三下四、不知自爱之人。你如真心爱我,须当敬我重我。我此生决无别念,就是钢刀架颈,也决意跟定了你。将来……将来如有洞房花烛之日,自然……自能...

k91191
今天
1
0
解决:modal中datePicker 选中时,会触发modal的hidden.bs.modal事件

最近项目中发现了一个bug,具体表现为选中模态框上datepicker组件上的日期时,会触发模态框的关闭事件,导致数据编辑无法正常进行。网上搜索了下,解决方法如下: $('.datepicker').on('hid...

Funcy1122
今天
0
0
Redis分布式锁的正确实现方式

前言 分布式锁一般有三种实现方式: 1.数据库乐观锁 2.基于Redis的分布式锁; 3.基于Zookeeper的分布式锁。本篇博客将介绍第二种方式,基于Redis实现分布式锁。虽然网上已经有各种介绍Redis...

大海201506
今天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部