多线程 - 生产者消费者问题
(一)生产者消费者问题:
1.题目:
采用Java 多线程技术,设计实现一个符合生产者和消费者问题的程序。 对一个对象(枪膛)进行操作,其最大容量是10颗子弹。 生产者线程是一个压入线程,它不断向枪膛中压入子弹;消费者线程是一个射出线程,它不断从枪膛中射出子弹。
2.分析:
这是个生产者与消费者问题,也是线程的同步问题, 为了防止执行个线程访问一个资源时出现忙等待,要使用的wait-notify函数,是两个线程交替执行。
3.解题步骤:
a.创建一个Factory类,包含Produce()方法和Consume()方法;
b.创建一个Producer线程,模拟生产子弹;
c.创建一个Consume线程,模拟消费子弹 ;
d.创建一个测试类Demo.
4.画图理解:
5.扩展 - 线程安全问题
(1)线程安全出现的原因:
a.多线程的环境下;(单线程不会出现安全问题)
b.多个线程拥有资源;
c.对共享资源的操作不是原子性的。(原子性是指一次操作要么执行完,要么不执行)
(2)那么怎么解决线程安全问题呢?
答:使用同步代码块。
格式:
sychronized (对象) {
要同步的代码块(你走我不走,我走你不走)
}
(二)代码体现:
1.创建一个Factory类

public class Factory {
String name;//加工厂名字
int MAX_SIZE;//最多加工子弹数目
int size;//当前剩余子弹数
public Factory(String name, int MAX_SIZE) {
this.name = name;
this.MAX_SIZE = MAX_SIZE;
}
//使用同步方法,保证线程安全
public synchronized void produce(){
while (size >= MAX_SIZE){
try {
//子弹充足,等待消费
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
try {
//加工子弹累了,休息会
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
//生产了一颗子弹
size++;
System.out.println("压入了一颗子弹,还剩下" + size + "颗");
//唤醒等待的所有线程
notifyAll();
}
//使用同步方法,保证线程安全
public synchronized void consume(){
while (size <= 0){
try {
//没有子弹了,等待
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
Thread.sleep(200);//射出子弹累了,休息会
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//射出了一颗子弹
size--;
System.out.println("射出了一颗子弹,还剩下" + size + "颗");
//唤醒等待的所有线程
notifyAll();
}
}
2.创建一个Producer类实现Runnable接口

public class Producer implements Runnable {
Factory factory;
public Producer(Factory factory) {
this.factory = factory;
}
@Override
public void run() {
//循环生产
while (true){
factory.produce();
}
}
}
3.创建一个Consume类实现Runnable接口

public class Consumer implements Runnable{
Factory factory;
public Consumer(Factory factory) {
this.factory = factory;
}
@Override
public void run() {
//循环消费
while (true){
factory.consume();
}
}
}
4.创建一个测试类Demo

public class Demo {
public static void main(String[] args) {
//创建一个加工厂
Factory factory = new Factory("子弹加工厂",200);
//创建一个生产者对象和一个消费者对象
Producer producer = new Producer(factory);
Consumer consumer = new Consumer(factory);
//创建一个生产者线程和一个消费者线程
Thread t1 = new Thread(producer);
Thread t2 = new Thread(consumer);
//启动线程
t1.start();
t2.start();
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix