(JAVA)-线程中的通信(生产者消费者模型)

news/2024/10/18 18:27:16/

在Java线程通信中,等待通知机制是最传统的方式,就是在一个线程进行了规定操作后,该线程就进入等待状态(wait), 等待其它线程执行完它们的指定代码过后,再将之前等待的线程唤醒(notify)。等待通知机制中使用到wait()、notify()和notifyAll()这三个方法,它们都属于Object这个类中,由于所有的类都从Object继承而来,因此,所有的类都拥有这些共有方法可供使用。而且,由于他们都被声明为final,因此在子类中不能覆写任何一个方法。

1.wait()

该方法只能被锁对象调用,调用能使当前线程跟锁绑定,能够进行后续的唤醒操作。而锁必定从同步方法或同步代码块中获得,因此方法只能写在同步方法或同步代码块内部。使用该方法当前线程进入阻塞状态,同时线程释放锁。直到被唤醒后重新进入就绪状态。

2.notify()

该方法也要在同步方法或同步块中调用,即在调用前,线程也必须要获得该对象的对象锁如果有多个线程等待,则线程规划器任意挑选出其中一个wait()状态的线程来发出通知,而未被选中的对象仍然保持阻塞状态。

注意:当在同步中调用wait()方法时,执行该代码的线程会立即放弃它在对象上的锁。然而在调用notify()时,并不意味着这时线程会放弃该对象锁,而是要等到程序运行完synchronized代码块后,当前线程才会释放锁,wait所在的线程也才可以获取该对象锁。

3.notifyAll()

该方法与notify()方法的工作方式相同,重要的一点差异是:

notifyAll使所有原来在该对象上wait的线程统统退出wait的状态(即全部被唤醒,不再等待notify或notifyAll,但由于此时还没有获取到该对象锁,因此还不能继续往下执行),变成等待获取该对象上的锁,一旦该对象锁被释放(notifyAll线程退出调用了notifyAll的synchronized代码块的时候),他们就会去竞争。如果其中一个线程获得了该对象锁,它就会继续往下执行,在它退出synchronized代码块,释放锁后,其它的已经被唤醒的线程将会继续竞争获取该锁,一直进行下去,直到所有被唤醒的线程都执行完毕。

下面举一个生产者消费者的例子:(生产者) 厨师是一个线程,能够生产拉面,(消费者)顾客是一个线程,能够吃拉面。

我们可以进行简单分析:

厨师(生产者):

判断桌上是否有拉面:1.有(等待)2.没(生产拉面,叫醒消费者)

顾客(消费者)

1.有(开吃)2.没(等待)

public class test {public static void main(String[] args) {Foodie f=new Foodie();Cook c=new Cook();f.start();c.start();}
}//桌子class Desk {
//    查看当前该哪个线程执行public static int foodFlag=0;//默认没有public static int num=0;
//锁对象public static Object lock=new Object();
}//顾客class Foodie extends Thread{@Overridepublic void run() {while(true){synchronized (Desk.lock){if(Desk.foodFlag==0){try {Desk.lock.wait();//让当前线程跟锁进行绑定} catch (InterruptedException e) {throw new RuntimeException(e);}}else{Desk.num++;System.out.println("吃了第"+Desk.num+"碗面条");Desk.foodFlag=0;Desk.lock.notifyAll();}}}}
}//厨师
class Cook extends Thread{@Overridepublic void run() {while(true){synchronized (Desk.lock){if(Desk.foodFlag==1){try {Desk.lock.wait();} catch (InterruptedException e) {throw new RuntimeException(e);}}else{Desk.foodFlag=1;System.out.println("做好了一碗面条");Desk.lock.notifyAll();}}}}
}


http://www.ppmy.cn/news/1279069.html

相关文章

Openwrt AP 发射 WiFi 信号

问题 想一次把 OpenWrt 路由器 wifi 问题给解决,完全取代路由器。 使用 倍控的 N5105 设备,有 mPCIe 接口,使用了 intel AX200 无线网卡,支持 2.4G 与 5G。 设置步骤 OpenWrt 镜像 第一次使用的镜像不支持 wifi,在…

AI-数学-初高中-因式分解

原教学视频链接:初高衔接】1等式变形方法回顾_哔哩哔哩_bilibili 1.乘法公式: 推导:ab(ab)-2ab 2.十字相乘法因式分解: 3.增添项法因式分解:

国际站店铺装修外贸平台alibaba鼠标经过渐变的效果功能代码代码生成器店铺装修旺铺旺铺装修生成器阿里巴巴国际站店铺怎么装修首页进入装修后台自定义内容模块

国际站店铺装修外贸平台alibaba鼠标经过渐变的效果功能代码代码生成器店铺装修旺铺旺铺装修生成器阿里巴巴国际站店铺怎么装修首页进入装修后台自定义内容模块 鼠标经过有个渐变的效果功能

安捷伦DSOX2024A示波器

参考波形 示波器的非易失参考波形存储器可以存储两个波形。比较这些参考波形与实时波形,并对已存储数据进行后分析和测量。您也可将波形数据存储到移动USB 存储器设备。这些数据还能调用到示波器的两个参考存储器的其中一个,进行全面的波形测量和分析。为…

Xcode15 iOS 17 Simulator 离线安装,模拟器安装

Xcode 15 安装包的大小相比之前更小,因为除了 macOS 的 Components,其他都需要动态下载安装,否则提示 iOS 17 Simulator Not Installed。 如果不安装对应的运行模拟库 无法真机和模拟器运行,更无法新建项目。但是由于模拟器安装包…

【Skynet 入门实战练习】事件模块 | 批处理模块 | GM 指令 | 模糊搜索

文章目录 前言事件模块批处理模块GM 指令模块模糊搜索最后 前言 本节完善了项目,实现了事件、批处理、模糊搜索模块、GM 指令模块。 事件模块 什么是事件模块?事件模块是用来在各系统之间传递事件消息的。 为什么需要事件模块?主要目的是…

关于游戏性能优化的技巧

关于游戏性能优化的技巧 游戏性能优化对象池Jobs、Burst、多线程间隔处理定时更新全局广播缓存组件缓存常用数据2D残影优化2D骨骼转GPU动画定时器优化DrawCall合批处理优化碰撞层优化粒子特效 游戏性能优化 好久没有在CSDN上面写文章了,今天突然看到鬼谷工作室技术…

天津web前端就业培训班,Web机构选择重点

Web前端培训是目前非常热门的培训领域之一。很多领域都会涉及到web前端开发,比如传统互联网、房地产、金融、游戏、影视传媒等行业都需要web前端技术的支持。越来越多的企业和个人也需要建立自己的网站和移动应用程序,因此市场对web前端工程师的需求是非…