一个例子学会生产者消费者模式

生产者消费者模式

题目描述:

采用Java 多线程技术,设计实现一个符合生产者和消费者问题的程序。

对一个对象(枪膛)进行操作,其最大容量是10颗子弹(特别注意,射击和上膛也都是需要时间的!!!!!)。

生产者线程是一个压入线程,它不断向枪膛中压入子弹;消费者线程是一个射出线程,它不断从枪膛中射出子弹。

注意,答案中的Gun(表示枪),ShoutTask(表示射击线程的设计任务), LoadTask(表示上膛线程的上膛任务),Test(测试类)分别定义在不同的java文件中

/**
 * 
 *  表示枪
 */
public class Gun {
    
    

  //枪膛中的子弹数
  private int bullets;

  /*
      消费者线程(射击线程),调用该方法射击(消费子弹)
   */
  public synchronized void shouting() {
    
    
    if (bullets <= 0) {
    
    
      //如果枪中没有子弹,则不射击
      try {
    
    
        this.wait();
      } catch (InterruptedException e) {
    
    
        e.printStackTrace();
      }
    } else {
    
    


      //枪中有子弹,则射击
      System.out.println(Thread.currentThread().getName()
          + "射出第" + bullets-- + "发子弹");

      // 通知上膛线程,压入子弹
      this.notifyAll();
    }
  }

  /*
      生产者线程调用该方法,上膛(压入子弹)
   */
  public synchronized void loading() {
    
    
    if (bullets >= 10) {
    
    
      //如果枪膛中的子弹是满的,则不上膛
      try {
    
    
        this.wait();
      } catch (InterruptedException e) {
    
    
        e.printStackTrace();
      }
    } else {
    
    
      //如果枪膛不满,则压入子弹
      System.out.println(Thread.currentThread().getName() + "压入第" + ++bullets + "发子弹");
      //模拟射击过程的时间延迟
      this.notifyAll();
    }
  }

}
/**
 *
 * 生产者线程,不停的压入子弹
 */
public class LoadTask implements Runnable{
    
    

  private Gun gun;

  public LoadTask(Gun gun) {
    
    
    this.gun = gun;
  }


  @Override
  public void run() {
    
    
    while (true) {
    
    

      //模拟每次上膛过程的延迟
      try {
    
    
        Thread.sleep(50);
      } catch (InterruptedException e) {
    
    
        e.printStackTrace();
      }
      gun.loading();
    }
  }
}
/**
 *
 * 消费者线程执行的射击代码, 不停的射击
 */
public class ShoutTask implements Runnable {
    
    

  private Gun gun;

  public ShoutTask(Gun gun) {
    
    
    this.gun = gun;
  }

  @Override
  public void run() {
    
    
    while (true) {
    
    

      //模拟每次射击过程的延迟
      try {
    
    
        Thread.sleep(50);
      } catch (InterruptedException e) {
    
    
        e.printStackTrace();
      }
      gun.shouting();
    }
  }
}
/**
 * 
 * 测试代码
 */
public class Test {
    
    

  public static void main(String[] args) {
    
    

    //射击线程和上膛线程操作的同一把枪
    Gun gun = new Gun();

    LoadTask loadTask = new LoadTask(gun);
    ShoutTask shoutTask = new ShoutTask(gun);

    new Thread(loadTask).start();
    new Thread(shoutTask).start();
    new Thread(loadTask).start();
    new Thread(shoutTask).start();

  }

}

猜你喜欢

转载自blog.csdn.net/qq_31702655/article/details/105252620