当前位置: 首页 > news >正文

网站用什么域名东莞网络营销策划

网站用什么域名,东莞网络营销策划,如何在网上推广网站,51zwd一起做网站wait 与 join 的核心区别这两个关键字都是用来协调线程之间执行顺序的工具,但有着本质区别:join:等待另一个线程彻底执行完毕后,当前线程才继续往下执行。wait:等待另一个线程执行notify/notifyAll后,当前线…

wait 与 join 的核心区别

这两个关键字都是用来协调线程之间执行顺序的工具,但有着本质区别:

  • join:等待另一个线程彻底执行完毕后,当前线程才继续往下执行。
  • wait:等待另一个线程执行notify/notifyAll后,当前线程就继续往下执行(不需要等待另一个线程完全执行完毕)

场景引入

假设现在有多个“线程”去ATM中“取钱”。(这就模拟了多个线程竞争同一把锁的场景
排在最前面的“线程”进入ATM之后,在它出来之前,后面的线程就无法进入。
假设当第一个线程进入之后,发现此时的ATM中并没有钱,那么它就会从ATM中出来。
那么问题来了:当第一个线程出来之后,第二个线程会直接进入ATM中吗
答案是不一定。
这里我们要明确的一点是,当多个线程竞争同一把锁时,当获取到锁的线程释放之后,其他哪个线程拿到这把锁是随机的,这是由于操作系统的调度是随机的。
此时要注意的是:

  1. 当前释放这个锁的线程是就绪状态
  2. 其他线程都属于在这个锁上进行阻塞等待,是阻塞状态

所以当前这个线程是有很大概率继续拿到这把锁的。
如果这个线程一直这样进行“反复横跳”,那么这就会导致其他线程一直不可以在CPU中执行,
这就是所谓的“线程饿死”现象。

上述场景就是wait和notify应用的典型场景
我们可以这样进行优化:当拿到锁的线程发现要执行的任务的时机尚未成熟的时候,就可以使用wait进行阻塞等待,在等待的这段时间里,其他的线程就有机会到CPU上去执行。
这个优化就可以节省许多不必要的开销。
以上述场景为例,当第一个线程发现ATM中并没有钱的时候,它就可以进行wait阻塞等待,当ATM中有钱之后,我们再使用notify关键字把它唤醒。

下面我们结合代码来详细讲解这两个关键字

代码解析

public static void main(String[] args) throws InterruptedException {Object object=new Object();System.out.println("wait之前");object.wait();System.out.println("wait之后");}

上述代码运行之后会报错,其中的IllegalMonitorStateException意为“非法的锁状态”。
这是为什么呢?
这是因为object.wait()这行代码在执行的第一步就是先释放object对象所对应的锁,那么能够释放锁的前提是object对象应该处于加锁状态,这样才可以释放。
下面我们给它加一个锁就可以让程序正常运行,示例如下:

  Object object=new Object();System.out.println("wait之前");synchronized (object){object.wait();}System.out.println("wait之后");

下面我们再来详细解析一下这些代码:

 synchronized (object){object.wait();}
  • 当运行到第一个大括号之后一直到object.wait();这行代码之前一直是加锁状态;
  • 当运行到这行代码时(wait在等待的过程中),是解锁状态(尽管这个时候并没有运行到右大括号);
  • 当运行完这行代码之后又是加锁状态;
  • 运行到右大括号就是解锁状态。

这里还要注意的一个细节是synchronized的锁对象和wait的锁对象必须是同一个~~~

wait和notify结合使用

 public static void main(String[] args) {Object locker1=new Object();Object locker2=new Object();Thread t1=new Thread(()->{try {System.out.println("wait之前");synchronized (locker1){locker1.wait();}System.out.println("wait之后");} catch (InterruptedException e) {e.printStackTrace();}});Thread t2=new Thread(()->{Scanner scanner=new Scanner(System.in);System.out.println("请输入任意内容唤醒t1");scanner.next();synchronized (locker1){locker1.notify();}});t1.start();t2.start();}


这里的locker1.notify();同样需要先拿到锁,再进行操作(这是Java中给出的限制)
wait是必须要搭配锁来使用的,因为wait需要先释放锁;
而notify操作在原则上说并不涉及到加锁解锁操作。
我们要知道的是,线程和锁本身就是操作系统所支持的特性。
在操作系统原生的API中,wait必须搭配锁来使用而notify则不需要。
我们这里给notify与锁搭配使用,是为了遵循Java给出的限制

  synchronized (locker1){locker1.wait();}synchronized (locker1){locker1.notify();}

这里要注意的是,这四处的锁对象必须保持一致。
如果这些锁对象是不同的,那么这两个线程之间就无法建立联系。

上面两个线程的先后顺序是随机的,但是我们要保证的是wait一定要在notify之前执行
如果先执行notify再执行wait,那么wait将无法被唤醒。

多个线程在同一个对象上进行wait,此时再用notify唤醒

public static void main(String[] args) {Object locker1=new Object();Thread t1=new Thread(()->{System.out.println("wait之前");synchronized (locker1){try {locker1.wait();} catch (InterruptedException e) {e.printStackTrace();}}System.out.println("t1wait之后");});Thread t2=new Thread(()->{System.out.println("wait之前");synchronized (locker1){try {locker1.wait();} catch (InterruptedException e) {e.printStackTrace();}}System.out.println("t2wait之后");});Thread t3=new Thread(()->{Scanner scanner=new Scanner(System.in);System.out.println("请输入任意内容唤醒线程");scanner.next();synchronized (locker1){locker1.notify();}});t1.start();t2.start();t3.start();}


这次唤醒的是t1,经过多次运行后我们发现,当只进行一次唤醒操作的时候,所唤醒的线程是随机的。
要想唤醒全部线程,要么就多执行几次locker1.notify()操作,要么就是用notifyAll()方法。

运行结果分析:

  • 当多个线程在同一个对象上等待时,一次 notify 操作只会随机唤醒其中一个线程
  • 要唤醒全部线程,可以多次调用notify(),或直接使用notifyAll()方法

虽然使用 notifyAll () 方法可以一次唤醒所有线程,但被唤醒的线程需要重新竞争锁 —— 只有一个线程能成功获取锁并继续执行。
其他线程会因竞争锁失败再次进入阻塞状态,直至持有锁的线程释放锁后重新参与竞争。

总结

wait 与 notify 是 Java 中实现线程间协作的重要机制,它们与锁紧密配合,能够有效解决线程竞争导致的问题(如线程饿死)。
正确理解和使用这两个方法,对于编写高效、可靠的多线程程序至关重要。使用时需特别注意锁对象的一致性和 wait/notify 的调用顺序,以避免程序出现难以调试的并发问题。

http://www.dtcms.com/a/569294.html

相关文章:

  • springboot 工具类 日期时间列表工具类详解:高效处理日期范围的利器
  • MYSQL第四次作业
  • 某游戏大厂分布式系统经典实战面试题解析
  • 某游戏大厂计算机网络面试问题深度解析(一)
  • C#基础:如何从现有类库复制一个新的类库,并且加入解决方案
  • C# 中 Entity Framework (EF) 和 EF Core 里的 `AsNoTracking` 方法
  • 基于视觉分析的加油站通话行为安全预警系统 构建加油安全新防线 通话行为模式识别 边缘计算通话动作监测设备
  • Traefik vs Spring Cloud:微服务架构的两种截然不同的技术路线
  • 郑州百度seo网站优广州网站开发外包哪家好
  • 高端网站建设推来客网络做seo推广公司
  • 数据挖掘6-AI总结
  • 网站首页域名如何设置访问快宿迁沭阳网站建设
  • 数据结构 —— 栈
  • 微信小程序开发案例 | 个人相册小程序(下)
  • 网站域名账号网址申请注册
  • 电商 API 数据交互最佳实践:JSON 格式优化、数据校验与异常处理
  • 重庆网站建设 沛宣织梦cms 官方网站
  • 零基础新手小白快速了解掌握服务集群与自动化运维(十七)ELK日志分析模块--Elasticsearch介绍与配置
  • 如何使用elasticdump进行elasticsearch数据还原
  • 【运维记录】Centos 7 基础命令缺失
  • 手写 RPC 框架
  • etcd 高可用分布式键值存储
  • 【ETCD】ETCD单节点二进制部署(TLS)
  • 小网站 收入请简述网站制作流程
  • 抗辐照MCU芯片在无人叉车领域的性能评估与选型建议
  • 什么是LLM?
  • Java/PHP源码解析:一站式上门维修服务系统的全栈实现
  • MPU6050 DMP 移植中 mpu_run_self_test () 自检失败的原因与解决方法
  • 系统端实现看门狗功能
  • 算法--二分查找(二)