多线程实现生产者消费者模型_JAVA_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > JAVA > 多线程实现生产者消费者模型

多线程实现生产者消费者模型

 2015/5/13 1:49:59  尤文武  程序员俱乐部  我要评论(0)
  • 摘要:读这篇文章之前,首先要弄明白java对象的两个方法,wait和notify或者notifyAll,那弄懂这两个方法又要知道一个概念,java中Object类有个对象锁,所有的对象都继承自Object类,所有每个对象都有个锁,而且java中的对象锁在同一时刻只能由一个线程持有,这是java在多线程编程中实现互斥的基础。那一个线程如何获得一个对象的锁呢?根据JDK源码,一个线程可以有3种方法获得对象锁,第一种是执行该对象实例的synchronized方法
  • 标签:实现 多线程 消费者 线程

? ? ? ?读这篇文章之前,首先要弄明白java对象的两个方法,wait和notify或者notifyAll,那弄懂这两个方法又要知道一个概念,java中Object类有个对象锁,所有的对象都继承自Object类,所有每个对象都有个锁,而且java中的对象锁在同一时刻只能由一个线程持有,这是java在多线程编程中实现互斥的基础。 那一个线程如何获得一个对象的锁呢?根据JDK源码,一个线程可以有3种方法获得对象锁,第一种是执行该对象实例的synchronized方法,第二种是执行对象中的synchronized代码块,执行类(非实例)的静态synchronized方法,最后需要注意的是一个对象的锁在同一个时间只能由一个线程持有,我们今天将要讨论的3个方法就是在线程获得了对象锁的情况下执行的。

? ? ? ? 先说一下wait方法,该方法的作用就是暂停当前线程,并释放占有的对象锁(当前线程一定要占有对象锁,否则会抛出异常),区别于sleep方法,sleep方法是Thread类的方法,也是暂停当前线程,但并不会释放锁(如果占有的话)。

? ? ? ? 接下来说notifyAll方法,作用是唤醒所有等待当前线程持有的对象锁的线程,同样的道理,调用notifyAll方法的线程必须持有对象锁,对象锁并不会在调用完notifyAll方法之后立刻被释放,需要等待当前线程(或者持有对象锁的方法,代码块)结束后才会被释放,锁被释放后,其它被唤醒的线程就会随机竞争,先得到该对象锁的线程将会进入执行, notify和notifyAll的区别就是notify只会随机唤醒一个线程,notifyAll会唤醒所有调用wait的线程。

? ? ? ?以下是运用wait和notify实现的生产者消费者的代码

package cn.javass.web.controller;

?

import java.util.Stack;

?

public class TestThead2

{

public static void main(String[] args)

{

ProductStack ps = new ProductStack();

Thread p = new Thread(new Producer(ps));

Thread c = new Thread(new Consumer(ps));

?

p.start();

c.start();

}

}

//模拟一个产品,包括一个属性id

class Product

{

String id;

?

Product(String id)

{

this.id = id;

}

}

//仓库类

class ProductStack

{

//仓库有个最大存储容量

int index = 6;

?

//仓库中货架

Stack<Product> products = new Stack<Product>();

?

//生产产品,并放入货架

publicsynchronizedvoid push(Product pc)

{

//如果货架上的产品已经满了,则停止生产

if (products.size() == index)

{

try

{

wait();

}

catch (InterruptedException e)

{

// TODO Auto-generated catch block

e.printStackTrace();

}

}

?

//生产一个产品

products.push(pc);

?

System.out.println("生成了 " + pc.id);

?

//此时货架肯定不是空的,通知消费者消费

notifyAll();

}

?

//从货架上取出产品供消费

publicsynchronizedvoid pop()

{

//如果货架上是空的,则停止消费

if (products.isEmpty())

{

try

{

wait();

}

catch (InterruptedException e)

{

// TODO Auto-generated catch block

e.printStackTrace();

}

}

//消费一个产品

Product pc = products.pop();

?

System.out.println("消费了 " + pc.id);

//此时货架肯定不是满的,通知生产者生产

notifyAll();

}

}

?

//生产者

class Producer implements Runnable

{

ProductStack ps;

?

Producer(ProductStack ps)

{

this.ps = ps;

}

?

@Override

publicvoid run()

{

//本次生产计划为20件商品

for (int i = 0; i < 20; i++)

{

ps.push(new Product(String.valueOf(i)));

}

}

?

}

?

//消费者

class Consumer implements Runnable

{

ProductStack ps;

?

Consumer(ProductStack ps)

{

this.ps = ps;

}

?

@Override

publicvoid run()

{

//消费计划为20件商品

for (int i =0;i<20;i++)

{

ps.pop();

?

//消费完一个商品之后停顿一段时间,接着消费,可以把这段代码注释掉,比较下输出结果有什么不同

try?

{

? ? ? ? ? ? ? ? Thread.sleep((int) (Math.random() * 20));

? ? ? ? ? ? }?

catch (InterruptedException e)?

{

? ? ? ? ? ? ? ? e.printStackTrace();

? ? ? ? ? ? }

}

}

?

?

}

?

?

发表评论
用户名: 匿名