线程协作(通信) 16
-
应用场景:1. 假设仓库中只能存放一件产品,生产者将生产出来的产品放入仓库,消费者将仓库中产品取走消费。
2.
被消费者取走为止。
3. 如果仓库放有产品,则消费者可以将产品取走消费,否则停止消费并等待,直到仓库中再次
放入产品为止。
这是一个线程同步问题,生产者和消费者共享同一个资源,并且生产者和消费者之间相互依赖,互为条件。
-
java提供了几个方法解决线程之间的通信问题:
注意:均是Object类的方法,都只能在同步方法或者同步代码块中使用,否则会抛出异常IIIegaIMoitorStateException。
-
解决式:1. 并发协作模型“生产者/消费者”--->管程法
2. 生产者:负责生产数据的模块(可能是方法,对象,线程,进程)
3. 消费者:负责生产数据的模块(可能是方法,对象,线程,进程)
4. 缓冲区:消费者不能直接使用生产者的数据,它们之间有个“缓冲区”
生产者将生产好的数据放入缓冲区,消费者从缓冲区拿出数据。
第二种:并发协作模型“生产者/消费者模式”-->信号灯法(trun , Flase)
package Runnable1;
/*
线程通信:使用两个线程打印1-100,线程1,线程2 交替打印
涉及三个方法:
wait():一旦执行此方法,当前线程就进入阻塞状态并释放同步监视器(锁)
notify():一旦执行此方法,就会唤醒被wait的一个线程,如果有多个线程被wait,就唤醒优先级高的线程
notifyAll:一旦执行此方法,就会唤醒所有被wait的线程
说明:
只能是出现在同步代码块或者同步方法中,调用者必须是同步代码块或者同步方法中同步监视器。
否则,会出现异常
三个方法是定义在java.lang.Object类中
面试题:sleep和wait的异常
相同点:一旦执行方法,都可以使得当前的线程进入阻塞状态。
不同点:1. 两个方法声明的位置不同,Thread类中声明sleep(),Object列类中声明wait()
2. 调用的要求不同:sleep()可以在任何需要的场景下调用,wait()必须使用同步代码块或同步方法中
3. 关于是否是否同步监视器:如果两个方法都使用在同步代码块或者同步方法中,sleep()不会释放锁,wait()会释放锁
*/
class Number implements Runnable
{
private int numeber=1;
package Runnable1;
/*
线程通信的应用:生产者消费者问题
分析:
是否是多线程问题?是,生产者线程,消费者线程
是否有共享数据?是店员(或产品)
如何来解决线程安全问题?同步机制:三种方法
是否涉及线程的通信?是
*/
class Clerk//
{
private int productCount=0;
//生产产品
//在这两个线程中一个时间内只有一个线程去跑
public synchronized void ProduceProduct()
{
if (productCount<20)
{
productCount++;
System.out.println(Thread.currentThread().getName()+":开始生产第"+productCount+"个产品");
//只要生产了一个产品,就唤醒消费者
notify();
}else {//不生产
try {
wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
//消费产品
public synchronized void consumeProduct()
{
if (productCount>0)
{
System.out.println(Thread.currentThread().getName()+":开始消费第"+productCount+"个产品");
productCount--;
notify();//只要消费一个产品,就把生产者唤醒生产
}else {//小于零
//等待
try {
wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
class Producer extends Thread//生产者
{
private Clerk clerk;//共享数据
public Producer(Clerk clerk)
{
this.clerk = clerk;
}
模拟生产者和消费者的案例:
- 创建馒头类(模拟共用的数据)
public
class
ManTou {
int
id;
public
ManTou(
int
id)
{
this
.id=id;
}
public
String toString()
{
return
"ManTou[id="
+
this
.id+
"]"
;
}
}
public
class
Basket {
int
index=
0
;
ManTou[] manTous=
new
ManTou[
6
];
//往篮子中放馒头
public
synchronized
void
push(ManTou manTou)
{
//篮子满了 需要等待
if
(index==
6
)
try
{
this
.wait();
}
catch
(InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
this
.notify();
//唤醒的是pop中的wait方法 一旦放馒头了 则说明篮子中有馒头了 取馒头的方法不用等了
this
.manTous[index]=manTou;
index++;
}
//从篮子中取馒头
public
synchronized
ManTou pop()
{
if
(index==
0
)
try
{
this
.wait();
}
catch
(InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
this
.notify();
//唤醒的是push中的wait方法 一旦取馒头了 则说明篮子有空位了 放馒头的行为就不用等了
index--;
return
this
.manTous[index];
}
}
public
class
Producer
extends
Thread{
Basket basket=
null
;
public
Producer(Basket basket)
{
this
.basket=basket;
}
//执行任务
public
void
run()
{
for
(
int
i=
1
;i<=
20
;i++)
{
ManTou manTou=
new
ManTou(i);
basket.push(manTou);
System.out.println(
"生产了"
+manTou);
try
{
this
.sleep(
200
);
}
catch
(InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
创建消费者(处理数据)
public
class
Consumer
extends
Thread{
Basket basket=
null
;
public
Consumer(Basket basket)
{
this
.basket=basket;
}
//执行任务
public
void
run()
{
for
(
int
i=
1
;i<=
20
;i++)
{
ManTou manTou=
this
.basket.pop();
System.out.println(
"消费了"
+manTou);
try
{
this
.sleep(
500
);
}
catch
(InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public
class
Test {
/**
* @param args
*/
public
static
void
main(String[] args) {
// TODO Auto-generated method stub
Basket basket=
new
Basket();
Producer producer=
new
Producer(basket);
Consumer consumer=
new
Consumer(basket);
producer.start();
consumer.start();
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY