Java线程:并发协作-生产者消费者模型
来源:互联网 发布:基尼系数数据 编辑:程序博客网 时间:2024/04/29 00:14
对于多线程程序来说,不管任何编程语言,生产者消费者模型都是最经典的。
实际上,准确的说应该是“生产者-消费者-仓储”模型,离开了仓储,生产者消费者模型就显得没有说服力了。
对于此模型,应该明确以下几点:
- 生产者仅仅在仓储未满时候生产,仓满则停止生产。
- 消费者仅仅在仓储有产品时候才能消费,仓空则等待。
- 当消费者发现仓储没有产品的时候会通知生产者生产。
- 生产者在生产出可消费产品时候,应该通知消费者去消费。
此模型将要结合java.lang.Object的wait与notify,notifyAll方法来实现以上的需求。这是非常重要的。
用代码实现如下:
class Godown{ public static final int max_size = 100 ;//最大库存量 public int curnum ; //当前库存量 public Godown() { // TODO 自动生成的构造函数存根 } public Godown(int curnum){ this.curnum = curnum; } public synchronized void produce(int neednum){ //生产指定数量的产品 while((neednum+curnum)>max_size){//检测是否需要生产 System.out.println("要生产的产品数量"+neednum+"超过剩余库存量"+(max_size-curnum)+",暂时不能执行生产任务1"); try{ //当前的生产线程等待 wait(); }catch (InterruptedException e){ e.printStackTrace(); } } //满足生产条件,则进行生产,更改当前库存量 curnum += neednum; System.out.println("已经生产了"+neednum+"个产品,现仓储量为"+curnum); //唤醒在此对象监视器上等待的所有线程 notifyAll(); } public synchronized void consume(int neednum){ while((curnum<neednum)) { //检测是否可以消费 try{ //当前的生产线程等待 wait(); }catch(InterruptedException e){ e.printStackTrace(); } }//满足消费条件,则进行消费,即更改当前库存量 curnum -= neednum; System.out.println("已经消费了"+neednum+"个产品,现仓储量为"+curnum); //唤醒在此监视器上等待的所有线程 notifyAll(); }}
/* 生产者 */class Producer extends Thread{ private int neednum ; // 生产产品数量 private Godown godown; //仓库 public Producer(int neednum,Godown godown) { // TODO 自动生成的构造函数存根 this.neednum = neednum ; this.godown = godown; } public void run(){ //生产指定数量的产品 godown.produce(neednum); }}
/* 消费者 */class Consumer extends Thread{ private int neednum ; // 生产产品数量 private Godown godown; //仓库 public Consumer(int needrum,Godown godown) { // TODO 自动生成的构造函数存根 this.neednum = needrum; this.godown = godown; } public void run(){ //消费指定数量的产品 godown.consume(neednum); }}
主程序实现代码:
package com.leetch.Threads;import java.lang.*; public class Test { public static void main(String args[]){ Godown godown = new Godown(30); Consumer c1 = new Consumer(50,godown) ; Consumer c2 = new Consumer(20, godown); Consumer c3 = new Consumer(30, godown); Producer p1 = new Producer(10, godown); Producer p2 = new Producer(10, godown); Producer p3 = new Producer(10, godown); Producer p4 = new Producer(10, godown); Producer p5 = new Producer(10, godown); Producer p6 = new Producer(10, godown); c1.start(); c2.start(); c3.start(); p1.start(); p2.start(); p3.start(); p4.start(); p5.start(); p6.start(); }}
一次执行结果如下:
说明:
对于本例,要说明的是当发现不能满足生产或者消费条件的时候,调用对象的wait( )方法,wait方法的作用是释放当前线程所获得的锁,并调用对象的notifyAll()方法,通知(唤醒)该对象上其他等待线程,使得继续执行。这样,整个生产者,消费者线程得以正确的协作执行。
nitifyAll()方法,起到一个通知作用,不释放锁,也不获取锁,只是告诉该对象上等待的线程“可以竞争执行了,都去执行吧!”。
本例中,如果消费者消费的仓储量达不到满足,而又没有生产者,则进程会一直处于等待状态,这当然是不对的,实际上可以将此例进行修改,修改为根据消费驱动生产,同时生产兼顾仓库,如果仓不满就生产,并对每次最大消费量做个限制,这样就不存在此问题了,当然,这样的例子更加复杂。
Java线程:并发协作-死锁
线程发生死锁可能性很小,即使看似可能发生死锁的代码,在运行时发生死锁的可能性也是小之又小。
发生死锁的原因一般是两个对象的锁相互等待造成的。
例如:
public class Test { public static void main(String[] args) { DeadlockRisk dead = new DeadlockRisk(); MyThread t1 = new MyThread(dead, 1, 2); MyThread t2 = new MyThread(dead, 3, 4); MyThread t3 = new MyThread(dead, 5, 6); MyThread t4 = new MyThread(dead, 7, 8); t1.start(); t2.start(); t3.start(); t4.start(); } } class MyThread extends Thread { private DeadlockRisk dead; private int a, b; MyThread(DeadlockRisk dead, int a, int b) { this.dead = dead; this.a = a; this.b = b; } @Override public void run() { dead.read(); dead.write(a, b); } } class DeadlockRisk { private static class Resource { public int value; } private Resource resourceA = new Resource(); private Resource resourceB = new Resource(); public int read() { synchronized (resourceA) { System.out.println("read():" + Thread.currentThread().getName() + "获取了resourceA的锁!"); synchronized (resourceB) { System.out.println("read():" + Thread.currentThread().getName() + "获取了resourceB的锁!"); return resourceB.value + resourceA.value; } } } public void write(int a, int b) { synchronized (resourceB) { System.out.println("write():" + Thread.currentThread().getName() + "获取了resourceA的锁!"); synchronized (resourceA) { System.out.println("write():" + Thread.currentThread().getName() + "获取了resourceB的锁!"); resourceA.value = a; resourceB.value = b; } } } }
0 0
- Java线程:并发协作-生产者消费者模型
- Java线程:并发协作-生产者消费者模型
- Java线程:并发协作-生产者消费者模型
- Java线程:并发协作-生产者消费者模型
- Java线程:并发协作-生产者消费者模型
- Java线程:并发协作-生产者消费者模型
- Java线程:并发协作-生产者消费者模型
- Java线程:并发协作-生产者消费者模型
- Java线程:并发协作-生产者消费者模型
- Java线程:并发协作-生产者消费者模型
- Java线程:并发协作-生产者消费者模型
- Java线程:并发协作-生产者消费者模型
- Java线程:并发协作-生产者消费者模型
- Java线程:并发协作-生产者消费者模型
- Java线程:并发协作-生产者消费者模型
- Java线程:并发协作-生产者消费者模型
- Java线程:并发协作-生产者消费者模型
- Java线程:并发协作-生产者消费者模型
- android GridView禁止上下滑动以及禁止滚动条显示的方法。
- linux防火墙状态查看、打开、关闭、永久关闭
- hdu4549 M斐波那契数列(矩阵快速幂)
- Unity3d-AssetBundle基本格式分析
- 城市、远方和故乡
- Java线程:并发协作-生产者消费者模型
- Django中如何使用django-celery完成异步任务
- 读入一个包含标点符号的字符串,将去掉标点符号之后的字符串输出
- 成功的秘诀在于长久的坚持和耐心
- Linux下安装MySQL
- 入门篇之 iOSOpenDev环境搭建(一)
- centos配置NFS服务简单流程
- iOS 网络编程模式总结
- thinkphp使用aapt获取apk信息