线程面试:生产者 消费者问题

来源:互联网 发布:php的发展前景 编辑:程序博客网 时间:2024/06/05 11:23

       

更多面试题请狠狠的点击 下载


       生产者消费者问题是研究多线程程序时绕不开的经典问题之一,它描述是有一块缓冲区作为仓库,生产者可以将产品放入仓库,消费者则可以从仓库中取走产品。解决生产者/消费者问题的方法可分为两类:(1)采用某种机制保护生产者和消费者之间的同步;(2)在生产者和消费者之间建立一个管道。第一种方式有较高的效率,并且易于实现,代码的可控制性较好,属于常用的模式。第二种管道缓冲区不易控制,被传输数据对象不易于封装等,实用性不强。因此本文只介绍同步机制实现的生产者/消费者问题。

同步问题核心在于:如何保证同一资源被多个线程并发访问时的完整性。常用的同步方法是采用信号或加锁机制,保证资源在任意时刻至多被一个线程访问。Java语言在多线程编程上实现了完全对象化,提供了对同步机制的良好支持。在Java中一共有四种方法支持同步,其中前三个是同步方法,一个是管道方法。

仓库代码段:

package com.work;/** * 仓库类 * 消费者 生产者 线程案例; * @author 张晨光 */public class Store {//仓库现有产品数量,最大库存为10private int count=0;//产品入库public synchronized void push(){if(count==10){try {System.out.println("仓库已满,等待消费");} catch (Exception e) {e.printStackTrace();}}try {Thread.sleep(1000);//入库耗时操作} catch (Exception e) {e.printStackTrace();}count++;System.out.println("生产了1个产品,仓库里还有"+count+"个产品");notify();//通知}//产品出库public synchronized void pop(){if(count==0){try {System.out.println("仓库已空,等待生产");} catch (Exception e) {e.printStackTrace();}}try {Thread.sleep(1000);//出库耗时操作;} catch (Exception e) {e.printStackTrace();}count--;System.out.println("消费了1个产品,仓库里还有"+count+"个产品");notify();}}

生产者代码段:

package com.work;/** * 生产者类: * @author 张晨光 */public class Producer implements Runnable{private Store store=null;public Producer(Store store){this.store=store;}public void run(){produce();}public void produce() {for(int i=0;i<50;i++){store.push();}}}

消费者代码段:

package com.suo;//父亲public class Father {public void say(){System.out.println("对孩子说,给我成绩单,我就把玩具给你");}public void get(){System.out.println("爸爸得到成绩单");}}
举这个例子的主要意思,是想让多多的理解一下生产者消费者模式,该模式我们平常可能用原生的比较少,但其实使用的场景一直都在用,比如线程池,连接池,等等。所以,知其然也知其所以然也很有必要,我们接着就代码来说明一下这个实现代码中的重点:

1.资源池有且只有一个。

2.synchronized,是锁对象,简单说一下:一个对象有且只有一把锁,当有多个synchronized方法或代码块都向该对象申请锁时,在同一时间,只会有一个线程得到该锁并运行,其它的就被阻塞了。

3.wait,是指该线程等待,wait有一个很重要的点,就是释放锁,上面也说了synchronized在同一时间只会有一个线程得到该锁并运行,所以,一旦wait后,就会释放锁,但当前线程等待下去,其它的线程再竞争这把锁。

4.notifyAll是指唤醒当前对象的所有等待的线程。

5.所有唤醒的线程会同时去竞争这把锁,但是JVM会随机选择一个线程并分配这把锁给该线程。

6.上面的synchronized wait notifyAll都是对一个对象进行操作,但这三个都是用在了资源池的类里面,所以,这也是资源池有且只能有一个的原因。



原创粉丝点击