金沙js333娱乐场(一道面课题)线程深切-生产者花费者难点

(一道面试题)线程深入-生产者消费者问题,试题生产者

一.生产者消费者问题?

1.生产者消费者问题(英语:Producer-consumer
problem),也称有限缓冲问题(英语:Bounded-buffer
problem),是一个多线程同步问题的经典案例。该问题描述了两个共享固定大小缓冲区的线程——即所谓的“生产者”和“消费者”——在实际运行时会发生的问题。生产者的主要作用是生成一定量的数据放到缓冲区中,然后重复此过程。与此同时,消费者也在缓冲区消耗这些数据。该问题的关键就是要保证生产者不会在缓冲区满时加入数据,消费者也不会在缓冲区中空时消耗数据。

2.解决办法:

要解决该问题,就必须让生产者在缓冲区满时休眠(要么干脆就放弃数据),等到下次消费者消耗缓冲区中的数据的时候,生产者才能被唤醒,开始往缓冲区添加数据。同样,也可以让消费者在缓冲区空时进入休眠,等到生产者往缓冲区添加数据之后,再唤醒消费者。通常采用进程间通信的方法解决该问题,常用的方法有信号灯法等。如果解决方法不够完善,则容易出现死锁的情况。出现死锁时,两个线程都会陷入休眠,等待对方唤醒自己。该问题也能被推广到多个生产者和消费者的情形。

二.编码实现生产者消费者问题

1.先上结果图:我定义了三个生产者分别时张飞,赵云还有关羽,两个消费者分别时曹操还有刘备.

先上结果图是为了说明:多线程说白了就是对cpu资源的抢夺,谁抢到了就可以执行自己的方法.

金沙js333娱乐场 1

 金沙js333娱乐场 2

2.生产者消费者实现步骤:

(1).因为生产者跟消费者共享一块区域,这里我将这块区域定义为“仓库”。

(2).仓库是有容量上限的,当数量达到上限后,生产者不允许继续生产产品.当前线程进入等待状态,等待其他线程唤醒。

(3).当仓库没有产品时,消费者不允许继续消费,当前线程进入等待状态,等待其他线程唤醒。

3.代码的实现:

(1).生产者跟消费者之间消费的是产品,所有先定义一个产品类:

public class Product {
 //定义产品的唯一ID
    int id;
    //定义构造方法初始化产品id
 public Product(int id) {
  this.id=id;
  // TODO Auto-generated constructor stub
 }
}

(2).定义一个仓库用来存放产品.

public class Repertory {
 //定义一个集合类用于存放产品.规定仓库的最大容量为10.
    public LinkedList<Product> store=new LinkedList<Product>();
 public LinkedList<Product> getStore() {
  return store;
 }
 public void setStore(LinkedList<Product> store) {
  this.store = store;
 }
 /* 生产者方法
  * push()方法用于存放产品.
  * 参数含义:第一个是产品对象
  * 第二个是线程名称,用来显示是谁生产的产品.
  * 使用synchronized关键字修饰方法的目的:
  * 最多只能有一个线程同时访问该方法.
  * 主要是为了防止多个线程访问该方法的时候,将参数数据进行的覆盖,从而发生出错.
  */
 public synchronized void push(Product p,String threadName)
 {
  /* 仓库容量最大值为10,当容量等于10的时候进入等待状态.等待其他线程唤醒
   * 唤醒后继续循环,等到仓库的存量小于10时,跳出循环继续向下执行准备生产产品.
   */ 
  while(store.size()==10){
   try {
    //打印日志
    System.out.println(threadName+"报告:仓库已满--->进入等待状态--->呼叫老大过来消费");
    //因为仓库容量已满,无法继续生产,进入等待状态,等待其他线程唤醒.
    this.wait();
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
  }
  //唤醒所有等待线程
  this.notifyAll();
  //将产品添加到仓库中.
  store.addLast(p);
  //打印生产日志
  System.out.println(threadName+"生产了:"+p.id+"号产品"+" "+"当前库存来:"+store.size());
  try {
   //为了方便观察结果,每次生产完后等待0.1秒.
   Thread.sleep(100);
  } catch (InterruptedException e) {
   e.printStackTrace();
  }

 }
 /* 消费者方法
  * pop()方法用于存放产品.
  * 参数含义:线程名称,用来显示是谁生产的产品.
  * 使用synchronized关键字修饰方法的目的:
  * 最多只能有一个线程同时访问该方法.
  * 主要是为了防止多个线程访问该方法的时候,将参数数据进行的覆盖,从而发生出错.
  */
 public synchronized void pop(String threadName){
  /* 当仓库没有存货时,消费者需要进行等待.等待其他线程来唤醒
   * 唤醒后继续循环,等到仓库的存量大于0时,跳出循环继续向下执行准备消费产品.
   */
  while(store.size()==0)
  {
   try {
    //打印日志
    System.out.println(threadName+"下命令:仓库已空--->进入等待状态--->命令小弟赶快生产");
    //因为仓库容量已空,无法继续消费,进入等待状态,等待其他线程唤醒.
    this.wait();
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
  }
  //唤醒所有等待线程
  this.notifyAll();
  //store.removeFirst()方法将产品从仓库中移出.
  //打印日志
  System.out.println(threadName+"消费了:"+store.removeFirst().id+"号产品"+" "+"当前库存来:"+store.size());
  try {
   //为了方便观察结果,每次生产完后等待1秒.
   Thread.sleep(1000);
  } catch (InterruptedException e) {
   e.printStackTrace();
  }
 }
}

(3).定义生产者

public class Producer implements Runnable {
 //定义一个静态变量来记录产品号数.确保每一个产品的唯一性.
 public static  Integer count=0;
 //定义仓库
    Repertory repertory=null;
    //构造方法初始化repertory(仓库)
 public Producer(Repertory repertory) {
  this.repertory=repertory;
 }
 /* run()方法因为该方法中存在非原子性操作count++;
  * 当多个线程同时访问时会发生count++的多次操作,导致出错
  * 为该方法添加同步错做,确保每一次只能有一个生产者进入该模块。
  * 这样就能保证count++这个操作的安全性.
  */
 @Override
 public void run() {
   while (true) {  
    synchronized(Producer.class){
     count++;
     Product product=new Product(count);
     repertory.push(product,Thread.currentThread().getName());
    }


  }

 }
}

(4).定义一个消费者

public class Consumer implements Runnable {
 //定义仓库
 Repertory repertory=null;
 //构造方法初始化repertory(仓库)
 public Consumer(Repertory repertory) {
  this.repertory=repertory;
 }
 //实现run()方法,并将当前的线程名称传入.
 @Override
 public  void run() {
  while(true){
   repertory.pop(Thread.currentThread().getName());
  }
 }

}

(5).测试类

public class TestDemo {
  public static void main(String[] args) {
 //定义一个仓库,消费者和生产者都使用这一个仓库
 Repertory repertory=new Repertory();
 //定义三个生产者(p1,p2,p3)
 Producer p1=new Producer(repertory);
 Producer p2=new Producer(repertory);
 Producer p3=new Producer(repertory);
 //定义两个消费者(c1,c2)
 Consumer c1=new Consumer(repertory);
 Consumer c2=new Consumer(repertory);
 //定义5个线程(t1,t2,t3,t4,t5)
 Thread t1=new Thread(p1,"张飞");
 Thread t2=new Thread(p2,"赵云");
 Thread t3=new Thread(p3,"关羽");
 Thread t4=new Thread(c1,"刘备");
 Thread t5=new Thread(c2,"曹操");
 //因为关羽跟赵云的生产积极性高,所以把他们的线程优先级调高一点
 t2.setPriority(10);
 t3.setPriority(10);
 //启动线程
 t1.start();
 t2.start();
 t3.start();
 t4.start();
 t5.start();
  }
}

三.总结:

生产者消费者问题我也是弄了好几天才略有头绪,弄完了就把自己的认识贴了出来,欢迎各位指点

 

 

一.生产者消费者问题? 1.生产者消费者问题(英语:Producer-consumer
problem),也称…

一.生产者消费者问题?

一.生产者消费者问题?

1.生产者消费者问题(英语:Producer-consumer
problem),也称有限缓冲问题(英语:Bounded-buffer
problem),是一个多线程同步问题的经典案例。该问题描述了两个共享固定大小缓冲区的线程——即所谓的“生产者”和“消费者”——在实际运行时会发生的问题。生产者的主要作用是生成一定量的数据放到缓冲区中,然后重复此过程。与此同时,消费者也在缓冲区消耗这些数据。该问题的关键就是要保证生产者不会在缓冲区满时加入数据,消费者也不会在缓冲区中空时消耗数据。

1.生产者消费者问题(英语:Producer-consumer
problem),也称有限缓冲问题(英语:Bounded-buffer
problem),是一个多线程同步问题的经典案例。该问题描述了两个共享固定大小缓冲区的线程——即所谓的“生产者”和“消费者”——在实际运行时会发生的问题。生产者的主要作用是生成一定量的数据放到缓冲区中,然后重复此过程。与此同时,消费者也在缓冲区消耗这些数据。该问题的关键就是要保证生产者不会在缓冲区满时加入数据,消费者也不会在缓冲区中空时消耗数据。

2.解决办法:

2.解决办法:

要解决该问题,就必须让生产者在缓冲区满时休眠(要么干脆就放弃数据),等到下次消费者消耗缓冲区中的数据的时候,生产者才能被唤醒,开始往缓冲区添加数据。同样,也可以让消费者在缓冲区空时进入休眠,等到生产者往缓冲区添加数据之后,再唤醒消费者。通常采用进程间通信的方法解决该问题,常用的方法有信号灯法等。如果解决方法不够完善,则容易出现死锁的情况。出现死锁时,两个线程都会陷入休眠,等待对方唤醒自己。该问题也能被推广到多个生产者和消费者的情形。

要解决该问题,就必须让生产者在缓冲区满时休眠(要么干脆就放弃数据),等到下次消费者消耗缓冲区中的数据的时候,生产者才能被唤醒,开始往缓冲区添加数据。同样,也可以让消费者在缓冲区空时进入休眠,等到生产者往缓冲区添加数据之后,再唤醒消费者。通常采用进程间通信的方法解决该问题,常用的方法有信号灯法等。如果解决方法不够完善,则容易出现死锁的情况。出现死锁时,两个线程都会陷入休眠,等待对方唤醒自己。该问题也能被推广到多个生产者和消费者的情形。

二.编码实现生产者消费者问题

二.编码实现生产者消费者问题

1.先上结果图:我定义了三个生产者分别时张飞,赵云还有关羽,两个消费者分别时曹操还有刘备.

1.先上结果图:我定义了三个生产者分别时张飞,赵云还有关羽,两个消费者分别时曹操还有刘备.

先上结果图是为了说明:多线程说白了就是对cpu资源的抢夺,谁抢到了就可以执行自己的方法.

先上结果图是为了说明:多线程说白了就是对cpu资源的抢夺,谁抢到了就可以执行自己的方法.

金沙js333娱乐场 3

金沙js333娱乐场 3

 金沙js333娱乐场 5

 金沙js333娱乐场 5

2.生产者消费者实现步骤:

2.生产者消费者实现步骤:

发表评论

电子邮件地址不会被公开。 必填项已用*标注