Java——多线程编程小实例:生产者-消费者问题(应用举例)

简介: Java——多线程编程小实例:生产者-消费者问题(应用举例)

1.Problem Descrption:


知识背景1:需要对操作系统中的消费者-生产者问题有一定的理解,在这里不再进行讲解了,大家可以百度或者查阅相应的书籍。

知识背景2:Java多线程的相关知识。

下面就直接上代码了!!!


2.Code:


2.1 BreadContainer类

package producer.and.consumer;
//面包容器类
public class BreadContainer {
  //面包厂的最大生产量
  public static final int maxNum=300;
  //当前面包的数量
  private int num;
  //无参构造方法
  public BreadContainer() {
  }
  //有参构造方法
  public BreadContainer(int num) {
    this.num=num;//初始化面包数量
  }
  //同步方法
  public synchronized void produceBread(int produceNum,String producerName) {
    //判断是否可以继续生产面包
    //如果当前面包数量 + 生产的面包数量 > 面包厂的最大生产量
    while(num + produceNum > maxNum) {
      //打印相关信息
      System.out.println(producerName + "要生产" + produceNum + "个,当前有"
          + num + "个,资源充足,不需要生产," + producerName + "去等待!");
      try {
        //此时无需生产  所以生产者等待
        wait();
      }catch(Exception e) {
        e.printStackTrace();
      }
    }
    //满足条件后,生产者可以生产面包,数量 = 当前面包数量 + 生产者生产的面包数量
    num = num + produceNum;
    //打印相关信息
    System.out.println(producerName + "生产了" + produceNum
          + "个,现在有" + num + "个!");
    //此时唤醒资源等待池中的所有线程
    notifyAll();
  }
  //同步方法
  public synchronized void consumeBread(int consumeNum,String consumerName) {
    //判断面包数量是否满足消费
    //如果所需消费的面包数量 > 当前面包数量
    while(consumeNum > num) {
      //打印相关信息
      System.out.println(consumerName + "要消费" + consumeNum + "个,由于现在只有"
          + num + "个," + consumerName + "于是去等待!");
      try {
        //数量不够,不能满足消费,所以消费者等待
        wait();
      }catch(Exception e) {
        e.printStackTrace();
      }
    }
    //满足条件后,数量充足,消费面包,数量 = 当前面包数量 - 所需消费的面包数量
    num = num - consumeNum;
    //打印相关信息
    System.out.println(consumerName + "消费了" + consumeNum
          + "个,现在还剩下" + num + "个!");
    //此时唤醒资源等待池中的所有线程
    this.notifyAll();
  }
}


2.2 Producer类

package producer.and.consumer;
//生产者类继承了Thread类
public class Producer extends Thread{
  //生产者一次生产的面包数量
  private int produceNum;
  //生产者需要访问的面包容器数量
  private BreadContainer bc;
  //无参构造方法
  public Producer() {
  }
  //有参构造方法
  public Producer(int produceNum,BreadContainer bc,String producerName) {
    //对生产者线程中的某些资源进行初始化
    this.produceNum=produceNum;
    this.bc=bc;
    this.setName(producerName);
  }
  //生产者的生产方法
  @Override
  public void run() {
    bc.produceBread(produceNum,this.getName());
  }
}


2.3 Consumer类

package producer.and.consumer;
//消费者类继承了Thread类
public class Consumer extends Thread{
  //记录消费者一次消费的数量
  private int consumeNum;
  //消费者需要访问的面包容器数量
  private BreadContainer bc;
  //无参构造方法
  public Consumer() {
  }
  //有参构造方法
  public Consumer(int consumeNum,BreadContainer bc,String consumerName) {
    //对消费者线程中的某些资源进行初始化
    this.consumeNum=consumeNum;
    this.bc=bc;
    this.setName(consumerName);
  }
  //消费者的消费方法
  @Override
  public void run() {
    bc.consumeBread(consumeNum,this.getName());
  }
}


2.4 Main主类

package producer.and.consumer;
//Main主类
public class Main {
  public static void main(String[] args) {
    //实例化一个面包容器类的对象,即初始面包数量为50
    BreadContainer bc=new BreadContainer(50);
    //创建相应的生产者和消费者线程对象
    Producer p1=new Producer(20,bc,"p1");
    Producer p2=new Producer(290,bc,"p2");
    Consumer c1=new Consumer(80,bc,"c1");
    Consumer c2=new Consumer(60,bc,"c2");
    //调用start()方法启动生产者-消费者线程
    c1.start();
    c2.start();
    p1.start();
    p2.start();
  }
}


2.5 Program running results

 

相关文章
|
1天前
|
Java
Java—多线程实现生产消费者
本文介绍了多线程实现生产消费者模式的三个版本。Version1包含四个类:`Producer`(生产者)、`Consumer`(消费者)、`Resource`(公共资源)和`TestMain`(测试类)。通过`synchronized`和`wait/notify`机制控制线程同步,但存在多个生产者或消费者时可能出现多次生产和消费的问题。 Version2将`if`改为`while`,解决了多次生产和消费的问题,但仍可能因`notify()`随机唤醒线程而导致死锁。因此,引入了`notifyAll()`来唤醒所有等待线程,但这会带来性能问题。
Java—多线程实现生产消费者
|
3天前
|
存储 安全 Java
Java多线程编程秘籍:各种方案一网打尽,不要错过!
Java 中实现多线程的方式主要有四种:继承 Thread 类、实现 Runnable 接口、实现 Callable 接口和使用线程池。每种方式各有优缺点,适用于不同的场景。继承 Thread 类最简单,实现 Runnable 接口更灵活,Callable 接口支持返回结果,线程池则便于管理和复用线程。实际应用中可根据需求选择合适的方式。此外,还介绍了多线程相关的常见面试问题及答案,涵盖线程概念、线程安全、线程池等知识点。
42 2
|
24天前
|
缓存 Java 调度
多线程编程核心:上下文切换深度解析
在现代计算机系统中,多线程编程已成为提高程序性能和响应速度的关键技术。然而,多线程编程中一个不可避免的概念就是上下文切换(Context Switching)。本文将深入探讨上下文切换的概念、原因、影响以及优化策略,帮助你在工作和学习中深入理解这一技术干货。
40 10
|
20天前
|
安全 算法 Java
Java多线程编程中的陷阱与最佳实践####
本文探讨了Java多线程编程中常见的陷阱,并介绍了如何通过最佳实践来避免这些问题。我们将从基础概念入手,逐步深入到具体的代码示例,帮助开发者更好地理解和应用多线程技术。无论是初学者还是有经验的开发者,都能从中获得有价值的见解和建议。 ####
|
20天前
|
Java 调度
Java中的多线程编程与并发控制
本文深入探讨了Java编程语言中多线程编程的基础知识和并发控制机制。文章首先介绍了多线程的基本概念,包括线程的定义、生命周期以及在Java中创建和管理线程的方法。接着,详细讲解了Java提供的同步机制,如synchronized关键字、wait()和notify()方法等,以及如何通过这些机制实现线程间的协调与通信。最后,本文还讨论了一些常见的并发问题,例如死锁、竞态条件等,并提供了相应的解决策略。
43 3
|
24天前
|
算法 调度 开发者
多线程编程核心:上下文切换深度解析
在多线程编程中,上下文切换是一个至关重要的概念,它直接影响到程序的性能和响应速度。本文将深入探讨上下文切换的含义、原因、影响以及如何优化,帮助你在工作和学习中更好地理解和应用多线程技术。
34 4
|
1天前
|
安全 Java API
【JavaEE】多线程编程引入——认识Thread类
Thread类,Thread中的run方法,在编程中怎么调度多线程
|
24天前
|
监控 Java 数据库连接
Java线程管理:守护线程与用户线程的区分与应用
在Java多线程编程中,线程可以分为守护线程(Daemon Thread)和用户线程(User Thread)。这两种线程在行为和用途上有着明显的区别,了解它们的差异对于编写高效、稳定的并发程序至关重要。
29 2
|
Java
Java多线程编程核心技术(三)多线程通信(下篇)
线程是操作系统中独立的个体,但这些个体如果不经过特殊的处理就不能成为一个整体。线程间的通信就是成为整体的必用方案之一,可以说,使线程间进行通信后,系统之间的交互性会更强大,在大大提高CPU利用率的同时还会使程序员对各线程任务在处理的过程中进行有效的把控与监督。
687 0
|
Java
Java多线程编程核心技术(三)多线程通信(上篇)
线程是操作系统中独立的个体,但这些个体如果不经过特殊的处理就不能成为一个整体。线程间的通信就是成为整体的必用方案之一,可以说,使线程间进行通信后,系统之间的交互性会更强大,在大大提高CPU利用率的同时还会使程序员对各线程任务在处理的过程中进行有效的把控与监督。
2565 0