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

import java.util.*;

public class ProducterConsumer{
private LinkedList<Object> box= new LinkedList<Object>();
private int max = 10 ;
public void start(){
new Producter().start();
new Consumer().start();
}
private class Producter extends Thread{
public void run(){
while(true){
synchronized(box){
try{
while(box.size()==max){
System.out.println("满了");
box.wait();//因为synchronized(box),所以要一致
}
Object o = new Object();
if(box.add(o)){
System.out.println("producter add a object");
}
box.notify();//因为synchronized(box),所以要一致
Thread.sleep((int)(Math.random()*3000)); }catch(InterruptedException e){
e.printStackTrace();
}
}
}
}
}
private class Consumer extends Thread{
public void run(){
while(true){
synchronized(box){
try{
while(box.size()==0){
System.out.println("空了");
box.wait();
}
box.removeLast();
System.out.println("consumer use a object");
box.notify();
Thread.sleep((int)(Math.random()*3000)); }catch(InterruptedException e){
e.printStackTrace();
}
} }
}
} public static void main(String[] args){
(new ProducterConsumer()).start();
}
}

wait/notify

通常,多线程之间需要协调工作。例如,浏览器的一个显示图片的线程displayThread想要执行显示图片的任务,必须等待下载线程 downloadThread将该图片下载完毕。如果图片还没有下载完,displayThread可以暂停,当downloadThread完成了任务 后,再通知displayThread“图片准备完毕,可以显示了”,这时,displayThread继续执行。
以上逻辑简单的说就是:如果条件不满足,则等待。当条件满足时,等待该条件的线程将被唤醒。在Java中,这个机制的实现依赖于wait/notify。等待机制与锁机制是密切关联的。例如:
synchronized(obj) {while(!condition) {obj.wait();}obj.doSomething();}

当线程A获得了obj锁后,发现条件condition不满足,无法继续下一处理,于是线程A就wait()。
在另一线程B中,如果B更改了某些条件,使得线程A的condition条件满足了,就可以唤醒线程A:
synchronized(obj) {condition = true;obj.notify();}

需要注意的概念是:
◆调用obj的wait(), notify()方法前,必须获得obj锁,也就是必须写在synchronized(obj) {...} 代码段内。
◆调用obj.wait()后,线程A就释放了obj的锁,否则线程B无法获得obj锁,也就无法在synchronized(obj) {...} 代码段内唤醒A。
◆当obj.wait()方法返回后,线程A需要再次获得obj锁,才能继续执行。
◆如果A1,A2,A3都在obj.wait(),则B调用obj.notify()只能唤醒A1,A2,A3中的一个(具体哪一个由JVM决定)。
◆obj.notifyAll()则能全部唤醒A1,A2,A3,但是要继续执行obj.wait()的下一条语句,必须获得obj锁,因此,A1,A2,A3只有一个有机会获得锁继续执行,例如A1,其余的需要等待A1释放obj锁之后才能继续执行。
◆当B调用obj.notify/notifyAll的时候,B正持有obj锁,因此,A1,A2,A3虽被唤醒,但是仍无法获得obj锁。直到B退出synchronized块,释放obj锁后,A1,A2,A3中的一个才有机会获得锁继续执行。

1、模拟做馒头、吃馒头。

public class ProducerConsumer{
public static void main(String args[]) {
SyncStack ss=new SyncStack();
Producer p=new Producer(ss);
Consumer c=new Consumer(ss);
new Thread(p).start();
new Thread(p).start();
new Thread(p).start();
new Thread(c).start();
}
}
//WoTou
class WoTou{
int id;
WoTou(int id){
this.id = id;
}
public String toString(){
return "WoTou:"+id;
}
}
//SyncStack
class SyncStack{
int index = 0;
WoTou[] arrWT = new WoTou[6]; public synchronized void push(WoTou wt){
while(index == arrWT.length){//不能用if,否则发现异常时就跳出if语句了,此时还是满的
try{
this.wait();
}catch(InterruptedException e){
e.printStackTrace();
}
}
this.notifyAll();
arrWT[index] = wt;
index++;
} public synchronized WoTou pop(){
while(index == 0){
try{
this.wait();
}catch(InterruptedException e){
e.printStackTrace();
}
}
this.notifyAll();
index--;
return arrWT[index];
}
}
//Producer
class Producer implements Runnable{
SyncStack ss = null;
Producer (SyncStack ss){
this.ss = ss;
} public void run(){
for(int i=0;i<60;i++){
WoTou wt=new WoTou(i);
ss.push(wt);
System.out.println("生产了:" + wt);
try{
Thread.sleep((int)(Math.random()*200));//sleep是静态方法 random()方法可获得0.0<x<1.0之间的随机数,返回double类型。
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
}
//Consumer
class Consumer implements Runnable{
SyncStack ss = null;
Consumer (SyncStack ss){
this.ss = ss;
} public void run(){
for(int i=0;i<20;i++){
WoTou wt = ss.pop();
System.out.println("消费了:" + wt);
try{
Thread.sleep((int)(Math.random()*2000));//sleep是静态方法
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
}

wait:属于Object类。锁定当前对象的线程,只能在synchronized方法里面使用wait。抛出InterruptedException异常,所以必须try catch。一旦wait,释放锁,之后必须用notify叫醒。

notify属于Object类中的,叫醒一个正在当前对象上wait的线程。

注意:每个wait后跟一个notify/notifyAll。线程wait后,只能等待其他线程叫醒自己。

比如同步方法pop中,当index==0时,消费者进入wait状态,此时只监听其他线程是否调用notify/notifyAll。如果一旦有线程调用了notify/notifyAll则此wait状态的进程被唤醒。整个程序只有push同步方法可能调用notify/notifyAll,所以当push方法上的进程运行时唤醒之前在wait状态的进程。

2、线程知识总结:进程、线程的概念;创建和启动线程的两种方法(Runnable,Thread),sleep,join,yield,synchronized,wait,notify/notifyAll

JAVA笔记16-生产者消费者问题的更多相关文章

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

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

  2. java多线程解决生产者消费者问题

    import java.util.ArrayList; import java.util.List; /** * Created by ccc on 16-4-27. */ public class ...

  3. java+反射+多线程+生产者消费者模式+读取xml(SAX)入数据库mysql-【费元星Q9715234】

    java+反射+多线程+生产者消费者模式+读取xml(SAX)入数据库mysql-[费元星Q9715234] 说明如下,不懂的问题直接我[费元星Q9715234] 1.反射的意义在于不将xml tag ...

  4. Java设计模式之生产者消费者模式

    Java设计模式之生产者消费者模式 博客分类: 设计模式 设计模式Java多线程编程thread 转载 对于多线程程序来说,不管任何编程语言,生产者和消费者模型都是最经典的.就像学习每一门编程语言一 ...

  5. java多线程模拟生产者消费者问题,公司面试常常问的题。。。

    package com.cn.test3; //java多线程模拟生产者消费者问题 //ProducerConsumer是主类,Producer生产者,Consumer消费者,Product产品 // ...

  6. JAVA多线程之生产者 消费者模式 妈妈做面包案例

    创建四个类 1.面包类 锅里只可以放10个面包 ---装面包的容器2.厨房 kitchen 生产面包 和消费面包  最多生产100个面包3.生产者4消费者5.测试类 多线程经典案例 import ja ...

  7. Java 多线程学习笔记:生产者消费者问题

    前言:最近在学习Java多线程,看到ImportNew网上有网友翻译的一篇文章<阻塞队列实现生产者消费者模式>.在文中,使用的是Java的concurrent包中的阻塞队列来实现.在看完后 ...

  8. 2.5多线程(Java学习笔记)生产者消费者模式

    一.什么是生产者消费者模式 生产者生产数据存放在缓冲区,消费者从缓冲区拿出数据处理. 可能大家会问这样有何好处? 1.解耦 由于有了缓冲区,生产者和消费者之间不直接依赖,耦合度降低,便于程序拓展和维护 ...

  9. 【多线程】java多线程实现生产者消费者模式

    思考问题: 1.为什么用wait()+notify()实现生产者消费者模式? wait()方法可以暂停线程,并释放对象锁 notify()方法可以唤醒需要该对象锁的其他线程,并在执行完后续步骤,到了s ...

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

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

随机推荐

  1. 使用 Unity* 进行并行处理的一种方法

    本文展示如何使用 Unity* 对游戏进行并行处理,以及如何使用游戏引擎执行与游戏相关的物理.在这个领域内,现实感是成功的一个重要标志.为了模拟真实世界,许多动作需要同时发生,这需要并行处理.创建两个 ...

  2. cocos2dx基础篇(24) 场景切换效果CCTransitionScene

    [3.x]     (1)去掉 "CC"     (2)卡牌翻转 TransitionFlip 中的样式 tOrientation // //1: kCCTransitionOri ...

  3. http 协议里的 200、301、302、401、403、405、500 分别代表什么?

    http 协议里的 200.301.302.401.403.405.500 分别代表什么? 详细描述: 打开某些网页时,无法正常打开,出现 200.301.302.401.403.405.500 这此 ...

  4. Sqlserver 2012附加数据库时出错提示操作系统错误5(拒绝访问)错误5120的解决办法

    环境: Win10系统 SQLSERver 2012 情况: 使用混合登陆方式,sa账户密码正确登陆后,附加.mdf文件出现此错误. 尝试解决方法一:使用管理员运行SQLSERver2012,sa账户 ...

  5. python 并发编程 协程池

    协程池 from gevent.pool import Pool from gevent import monkey;monkey.patch_all() import gevent from gev ...

  6. C语言Ⅰ博客作业03

    一. 这个作业属于那个课程 C语言程序设计II 这个作业要求在哪里 https://edu.cnblogs.com/campus/zswxy/CST2019-3/homework/8718 我在这个课 ...

  7. CDH日常运维

    1/ 作业有问题: 查log,没log再跑一次查log. 如果没有log的情况,比如hiveserver2挂了,查strr. 2/ 查集群名字 #看hdfs集群的名字,在cdh的hdfs配置中查:na ...

  8. poj2407(欧拉函数模板题)

    题目链接:https://vjudge.net/problem/POJ-2407 题意:给出n,求0..n-1中与n互质的数的个数. 思路:欧拉函数板子题,先根据唯一分解定理求出n的所有质因数p1,p ...

  9. jquery validate 自定义校验方法

    1.引入JS jquery.min.js jquery.validate.min.js messages_zh.min.js 2.添加验证方法,第一个参数为验证方法的名称,第二个参数为验证方法. $. ...

  10. 云服务器以及linux操作系统打开防火墙,在墙上开一个小口

    在服务器运行时,需要在某个端口上开一个小口,以供外部访问 执行命令/sbin/iptables -I INPUT -p tcp --dport 8080 -j ACCEPT 8080为端口号,需要开的 ...