黑马程序员——生产者和消费者问题
来源:互联网 发布:徐州淘宝产业链 编辑:程序博客网 时间:2024/06/05 03:07
生产者消费者问题是学习多线程时绕不开的经典问题之一,它描述是有一块缓冲区作为共享资源,生产者可以将产品放入在共享空间,消费者则可以从该共享空间中消耗资源,在这个问题中要保证以下几点:
(1)同一时间内只有一个生产者进行生产。
(2)同一时间只有一个消费者进行消费。
(3)生产者生产时消费者不能消费。
(4)消费者消费时生产者不能生产。
(5)共享空间空时消费者不能继续消费。
(6)共享空间满时生产者不能继续生产。
一、wait()/notify()方法
wait()/notify()方法是基类Object的两个方法,也就意味着所有Java类都会拥有这两个方法,这样,我们就可以为任何对象实现同步机制。
wait()方法:当缓冲区已满、空时,生产者/消费者线程停止自己的执行,放弃锁,使自己处于等待状态,让其他线程执行。
notify()方法:当生产者/消费者向缓冲区放入/取出一个产品时,向其他等待的线程发出可执行的通知,同时放弃锁,使自己处于等待状态。
class Resource{ private String name; private int counts=0; public boolean flag=false; //是否有资源的判断标识 //生产函数。 public synchronized void set(String name){ //判端是否有资源,有就放弃执行权,没有就生产 if(flag){ try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } this.name=name; counts++; System.out.println(Thread.currentThread().getName()+":"+name+"======="+counts); this.flag=true;//生产后将资源标识置为真 notify();//唤醒线程 } //消费函数。 public synchronized void out(){ //判端是否有资源,有就消费掉,没有就放弃执行权 if(!flag){ try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(Thread.currentThread().getName()+":"+name+".................."+counts); this.flag=false;//消费后将标识置为假 notify();//唤醒线程 }} //生产者类,实现Runnable接口class Producer implements Runnable{ private Resource res; public Producer(Resource res){ this.res=res; } @Override public void run() { while(true){ res.set("包子"); } }} //消费者类,实现Runnable接口class Consumer implements Runnable{ private Resource res; public Consumer(Resource res){ this.res=res; } @Override public void run() { while(true){ res.out(); } }} public class ProducerConsumer { public static void main(String[] args) { Resource res=new Resource(); Producer pro=new Producer(res); Consumer con=new Consumer(res); new Thread(pro).start();//生产者1线程启动 new Thread(pro).start();//生产者2线程启动 new Thread(con).start();//消费者1线程启动 new Thread(con).start();//消费者2线程启动 }}
二、await()/signal()方法
在JDK5.0之后,Java提供了更加健壮的线程处理机制,包括同步、锁定、线程池等,它们可以实现更细粒度的线程控制。await()和signal()就是其中用来做同步的两种方法,它们的功能基本上和wait() / nofity()相同,完全可以取代它们,但是它们和新引入的锁定机制Lock直接挂钩,具有更大的灵活性。通过在Lock对象上调用newCondition()方法,将条件变量和一个锁对象进行绑定,进而控制并发程序访问竞争资源的安全。下面来看代码:
import java.util.concurrent.locks.*;//生产者和消费者共享的资源class Resource{ private String name;private int counts=0;private Lock lock=new ReentrantLock();private Condition condition_pro=lock.newCondition();private Condition condition_con=lock.newCondition();public boolean flag=false; //是否有资源的判断标识//生产函数。public void set(String name){lock.lock();//加锁//判端是否有资源,有就放弃执行权,没有就生产try {while(flag){condition_pro.await();}this.name=name;counts++;System.out.println(Thread.currentThread().getName()+":"+name+"======="+counts);this.flag=true;//生产后将资源标识置为真condition_con.signal();} catch (InterruptedException e) {e.printStackTrace();}finally{lock.unlock();//解锁}}//消费函数。public void out(){lock.lock();//判端是否有资源,有就消费掉,没有就放弃执行权try {while(!flag){condition_con.await();}System.out.println(Thread.currentThread().getName()+":"+name+".................."+counts);this.flag=false;//消费后将标识置为假condition_pro.signal();//唤醒线程} catch (InterruptedException e) {e.printStackTrace();}finally{lock.unlock();}}}//生产者类,实现Runnable接口class Producer implements Runnable{private Resource res;public Producer(Resource res){this.res=res;}@Overridepublic void run() { while(true){res.set("包子");}}}//消费者类,实现Runnable接口class Consumer implements Runnable{private Resource res;public Consumer(Resource res){this.res=res;}@Overridepublic void run() {while(true){res.out();}}}public class ProducerConsumer {public static void main(String[] args) {Resource res=new Resource();Producer pro=new Producer(res);Consumer con=new Consumer(res);new Thread(pro).start();//生产者1线程启动new Thread(pro).start();//生产者2线程启动new Thread(con).start();//消费者1线程启动new Thread(con).start();//消费者2线程启动}}这种多生产者和消费者JDK1.5升级版,使用Lock替代了synchrnized,Condition替代了Object监视器方法。好处是一个锁可以对应多个Condition对象,值得注意的是释放锁的工作一定要执行。
- 黑马程序员——生产者和消费者问题
- 黑马程序员_生产者和消费者问题
- 黑马程序员——Java---多线程-生产者和消费者
- 黑马程序员——生产者消费者详解
- 黑马程序员:生产者消费者问题思考
- 黑马程序员----多线程之生产者消费者问题
- 黑马程序员-java多线程生产者消费者问题
- 黑马程序员--生产者和消费者模式
- 黑马程序员——多线程操作经典实例:生产者消费者问题
- 黑马程序员——生产者消费者问题之线程间通信
- 黑马程序员——生产者消费者问题之线程间通信
- 黑马程序员——利用生产者和消费者模式讨论notify()方法的运用
- 黑马程序员_线程间的通讯和生产者和消费者之间的问题
- 黑马程序员_11线程同步问题、生产者消费者问题
- 黑马程序员-生产者消费者模式
- 黑马程序员-Thread-生产者消费者
- 黑马程序员-关于生产者消费者和火车票出售的线程问题
- 黑马程序员-多线程(生产者与消费者问题)
- Java中Map接口(传智播客毕老师视频讲解)
- 如何看待「封锁 Google 第一案」的开庭审理?
- Big Little迁移之Idle-pull
- 数据结构笔试面试题
- ios 时间与字符串相互转换,包含时区的转换
- 黑马程序员——生产者和消费者问题
- jQuery筛选器children()
- Fragment的使用
- 115个Java面试题和答案——终极列表(上)
- 动态规划
- 115个Java面试题和答案——终极列表(下)
- NYOJ 题目214 单调递增子序列(二)(动态规划,二分)
- linux内核链表笔记
- switch case 语句要注意!!!