多线程之生产消费问题
2014-05-26 16:21
232 查看
问题:一个仓库最多容纳6个产品,制造商现在要制造20件产品存入仓库,消费者要从仓库取出20件产品来消费,制造商生产产品和消费者消费产品的速度很可能不一样!
总结:
1:a.wait():将执行a.wait()的线程进入阻塞状态,让出CPU的控制权,释放对a的锁定。
2:a.notify():叫醒正在等待的线程,使其进入就绪状态,需要注意的是,此时即使没有线程在等待,调用这个方法也是不会出错的。
3:a.notifyAll():叫醒其他所有因为执行了wait()而陷入阻塞的线程。
4:不能使用sleep(XXX),和设置优先级来控制哪一个线程先执行,因为这些都不能是线程立即进入运行状态,而是进入就绪状态。
注:notify()和notifyAll()不是叫醒调用他们的当前线程,而是叫醒其他因为调用wait()而陷入阻塞的线程。
/** * 定义仓库 * @author Liao */ class SyncStack{ /*用数组来表示仓库的容量*/ char[] data = new char[6]; /*定义数组下标的标示*/ int cnt = 0; /** * 把生产出来的产品放入仓库中 * 这里使用线程同步的关键字synchronized * 执行push()方法的时候就不能执行pop()操作!!!! * @param ch 模拟产品的字符 */ public synchronized void push(char ch){ /*如果仓库已满*/ while (cnt == data.length){//这是一个while,也就是说如果为true的话,将会一直执行 /*如果仓库满了的话,我们就使得生产线程进入等待状态【注:这里不能通过sleep()来控制哈,谁知道消费者啥时候来取,谁知道睡多长时间呢?所以要使用wait()进行等待】*/ try { this.wait(); } catch (Exception e) { e.printStackTrace(); } } /*通知正在等待的线程进入就绪状态(可能不会立即执行),即使没有线程在等待也不会报错,所以一定要加上这句,否则正在等待的线程可能会陷入阻塞*/ this.notify(); /*把产品出入仓库*/ data[cnt] = ch; /*数组下标加一*/ cnt ++; System.out.printf("生产了: %c\n", ch); System.out.printf("容器中现在共有%d个字符!\n\n", cnt); } /** * 消费者从仓库中取出产品 * 这里也要使用线程同步 * 执行pop()方法的时候就不能执行push()方法 * @throws */ public synchronized char pop() { char ch; /*如果仓库中没有产品*/ while (cnt == 0){ /*如果仓库中没有产品,我们就让消费线程进入等待状态*/ try { this.wait(); } catch (Exception e) { e.printStackTrace(); } } /*通知正在等待的线程进入就绪状态(可能不会立即执行),即使没有线程在等待也是不会报错的,所以一定要加上这句,否则正在等待的线程可能会陷入阻塞*/ this.notify(); /*取出最上面的产品*/ ch = data[cnt - 1]; /*数组的下标要减去1*/ cnt --; System.out.printf("取出: %c\n", ch); System.out.printf("容器中现在共有%d个字符!\n\n", cnt); return ch; } } /** * 定义生产者 * @author Liao */ class Producer implements Runnable{ /*定义仓库【生产者生产处产品就把产品放入仓库中】*/ public SyncStack s = null; /*构造函数,把仓库传进来*/ public Producer(SyncStack s) { this.s = s; } /** * 生产操作 */ public void run() { char ch; /*生产20个产品*/ for (int i=0; i<20; i++){ /*一个字符模拟一个产品*/ ch = (char) ('a' + i); /*把制造出来的产品放入仓库中*/ s.push(ch); } } } /** * 定义消费者 * @author Liao */ class Consumer implements Runnable{ /*定义仓库【消费者从仓库中取出产品】*/ public SyncStack s = null; /*构造函数*/ public Consumer(SyncStack s) { this.s = s; } /*消费者消费产品*/ public void run() { /*遍历消费20个产品*/ for (int i=0; i<20; i++){ /*从仓库中取出一个产品*/ s.pop(); /*每隔500ms取出一个产品*/ try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } } } /** * 测试类 * @author Liao * */ public class ProducerConsumerTest { public static void main(String[] args) { /*创建仓库*/ SyncStack ss = new SyncStack(); /*创建生产者*/ Producer producer = new Producer(ss); /*创建消费者*/ Consumer consumer = new Consumer(ss); /*创建生产者线程*/ Thread pThread = new Thread(producer); /*创建消费者线程*/ Thread cThread = new Thread(consumer); /*启动两个线程*/ pThread.start(); cThread.start(); } }
总结:
1:a.wait():将执行a.wait()的线程进入阻塞状态,让出CPU的控制权,释放对a的锁定。
2:a.notify():叫醒正在等待的线程,使其进入就绪状态,需要注意的是,此时即使没有线程在等待,调用这个方法也是不会出错的。
3:a.notifyAll():叫醒其他所有因为执行了wait()而陷入阻塞的线程。
4:不能使用sleep(XXX),和设置优先级来控制哪一个线程先执行,因为这些都不能是线程立即进入运行状态,而是进入就绪状态。
注:notify()和notifyAll()不是叫醒调用他们的当前线程,而是叫醒其他因为调用wait()而陷入阻塞的线程。
相关文章推荐
- 多线程之偷了个懒之经典生产消费问题
- Java 多线程间通信 多生产 多消费问题
- 多线程生产消费问题
- 生产者消费者问题 这是一个非常经典的多线程题目,题目大意如下:有一个生产者在生产产品,这些产品将提供给若干个消费者去消费,为了使生产者和消费者能并发执行,在两者之间设置一个有多个缓冲区的缓冲池,生产者
- Java多线程的单生产单消费和多生产多消费问题的解决
- java多线程之生产消费问题
- 生产者消费者问题 这是一个非常经典的多线程题目,题目大意如下:有一个生产者在生产产品,这些产品将提供给若干个消费者去消费,为了使生产者和消费者能并发执行,在两者之间设置一个有多个缓冲区的缓冲池,生产者
- 多线程生产消费问题
- Java中多线程的多生产多消费问题的解决方案
- 多线程经典问题:馒头问题 生产和消费问题(线程的通信问题)
- 多线程的经典案例(生产消费问题)
- --多线程中,单生产单消费,多生产多消费的问题
- 多线程中的多生产多消费问题
- 【代码练习6】利用多线程生产消费问题实现熊吃蜂蜜问题
- 生产者消费者问题 这是一个非常经典的多线程题目,题目大意如下:有一个生产者在生产产品,这些产品将提供给若干个消费者去消费,为了使生产者和消费者能并发执行,在两者之间设置一个有多个缓冲区的缓冲池,生产者
- 多线程多生产多消费问题以及解决
- 多线程中多生产多消费问题
- 条件变量实现生产消费问题
- 第三周第一天(【正则表达式的应用】【卖票问题】【同一个账号两人同时取钱】【生产消费问题】【join】【死锁问题】)
- 多线程之信号量--生产消费者问题