Java中的Object的Wait() 和notify()方法使用时应注意的地方和Thread中的sleep()方法

2024-03-17 11:18

本文主要是介绍Java中的Object的Wait() 和notify()方法使用时应注意的地方和Thread中的sleep()方法,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1)sleep 是线程类(Thread)的方法,导致此线程暂停执行指定时间,给执行机会给其他线程,但是监控状态依然保持,到时后会自动恢复。调用sleep 不会释放对象锁。
wait 是Object 类的方法,对此对象调用wait 方法导致本线程放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象发出notify 方法(或notifyAll)后本线程才进入对象锁定池准备获得对象锁进入运行状态。

1、这两个方法来自不同的类分别是Thread和Object
2、最主要是sleep方法没有释放锁,而wait方法释放了锁,使得其他线程可以使用同步控制块或者方法。
3、wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在任何地方使用(使用范围)

<ol class="linenums" style="margin: 0px; padding: 0px 0px 0px 10px; border: none; list-style-position: outside; background: transparent;"><li class="L0" style="color: rgb(153, 153, 153); list-style-type: decimal; list-style-position: initial; margin: 0px; padding: 0px 0px 0px 10px; border: none; line-height: 20px; background-color: rgb(250, 250, 250);"><span class="kwd" style="margin: 0px; padding: 0px; border: 0px; color: rgb(0, 0, 139); font-weight: bold; background: transparent;">synchronized</span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: rgb(0, 0, 0); background: transparent;">(</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: rgb(0, 0, 0); background: transparent;">x</span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: rgb(0, 0, 0); background: transparent;">){</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: rgb(0, 0, 0); background: transparent;"></span>
</li><li class="L1" style="color: rgb(153, 153, 153); list-style-type: decimal; list-style-position: initial; margin: 0px; padding: 0px 0px 0px 10px; border: none; line-height: 20px; background-color: rgb(250, 250, 250);"><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: rgb(0, 0, 0); background: transparent;">  x</span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: rgb(0, 0, 0); background: transparent;">.</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: rgb(0, 0, 0); background: transparent;">notify</span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: rgb(0, 0, 0); background: transparent;">()</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: rgb(0, 0, 0); background: transparent;"></span>
</li><li class="L2" style="list-style-type: decimal; list-style-position: initial; margin: 0px; padding: 0px 0px 0px 10px; border: none; line-height: 20px; background-color: rgb(250, 250, 250);"><span style="margin: 0px; padding: 0px; border: 0px; color: rgb(255, 0, 0); background: transparent;"><span class="pln" style="margin: 0px; padding: 0px; border: 0px; background: transparent;">  </span><span class="com" style="margin: 0px; padding: 0px; border: 0px; background: transparent;">//或者wait()</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; background: transparent;"></span>
</span></li><li class="L3" style="color: rgb(153, 153, 153); list-style-type: decimal; list-style-position: initial; margin: 0px; padding: 0px 0px 0px 10px; border: none; line-height: 20px; background-color: rgb(250, 250, 250);"><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: rgb(0, 0, 0); background: transparent;">  </span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: rgb(0, 0, 0); background: transparent;">}</span></li></ol>

4、sleep必须捕获异常,而wait,notify和notifyAll不需要捕获异常

sleep方法属于Thread类中方法,表示让一个线程进入睡眠状态,等待一定的时间之后,自动醒来进入到可运行状态,不会马上进入运行状态,因为线程调度机制恢复线程的运行也需要时间,一个线程对象调用了sleep方法之后,并不会释放他所持有的所有对象锁,所以也就不会影响其他进程对象的运行。但在sleep的过程中过程中有可能被其他对象调用它的interrupt(),产生InterruptedException异常,如果你的程序不捕获这个异常,线程就会异常终止,进入TERMINATED状态,如果你的程序捕获了这个异常,那么程序就会继续执行catch语句块(可能还有finally语句块)以及以后的代码

注意sleep()方法是一个静态方法,也就是说他只对当前对象有效,例如t是一个线程,通过指定t.sleep()让t对象进入sleep,这样的做法是错误的,它只会是使当前线程被sleep 而不是t线程

wait属于Object的成员方法,一旦一个对象调用了wait方法,必须要采用notify()和notifyAll()方法唤醒该进程;如果线程拥有某个或某些对象的同步锁,那么在调用了wait()后,这个线程就会释放它持有的所有同步资源,而不限于这个被调用了wait()方法的对象。wait()方法也同样会在wait的过程中有可能被其他对象调用interrupt()方法而产生

2)Wait()和notify():如果条件不满足,则等待。当条件满足时,等待该条件的线程将被唤醒。一般用在synchronized机制中。

例如:线程A

   synchronized(obj) {

               while(!condition) {

                         obj.wait();

                 }

                obj.doSomething();

.....

  }

当线程A获得了obj锁后,发现条件condition不满足,无法继续下一处理,于是线程A就wait()。在另一线程B中,如果B更改了某些条件,使得线程A的condition条件满足了,就可以唤醒线程A。

线程B

      synchronized(obj) {

              condition = true;

              obj.notify();

        }

需要注意的概念是:  

   1.调用obj的wait(), notify()方法前,必须获得obj锁,也就是必须写在synchronized(obj) {……} 代码段内(或synchronized方法中)。  

   2.调用obj.wait()后,线程A就释放了obj的锁,否则线程B无法获得obj锁,也就无法在synchronized(obj) {……} 代码段内唤醒A.  

   3.当obj.wait()方法返回后,线程A需要再次获得obj锁,才能继续执行。  

   4.如果A1,A2,A3都obj.wait(),则B调用obj.notify()只能唤醒A1,A2,A3中的一个(具体哪一个由JVM决定)。  

   5.obj.notifyAll()则能全部唤醒A1,A2,A3,但是要继续执行obj.wait()的下一条语句,必须获得obj锁,因此,A1,A2,A3只有一个有机会获得锁继续执行,例如A1,其余的需要等待A1释放obj锁之后才能继续执行。

   6.当B调用obj.notify/notifyAll的时候,B正持有obj锁,因此,A1,A2,A3虽被唤醒,但是仍无法获得obj锁。直到B退出synchronized块,释放obj锁后,A1,A2,A3中的一个才有机会获得锁继续执行。

3)为什么wait(),notify()方法要和synchronized一起使用?

因为wait()方法是通知当前线程等待并释放对象锁,notify()方法是通知等待此对象锁的线程重新获得对象锁,然而,如果没有获得对象锁,wait方法和notify方法都是没有意义的,即必须先获得对象锁,才能对对象锁进行操作,于是,才必须把notify和wait方法写到synchronized方法或是synchronized代码块中了。

这篇关于Java中的Object的Wait() 和notify()方法使用时应注意的地方和Thread中的sleep()方法的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/818786

相关文章

JVM 的类初始化机制

前言 当你在 Java 程序中new对象时,有没有考虑过 JVM 是如何把静态的字节码(byte code)转化为运行时对象的呢,这个问题看似简单,但清楚的同学相信也不会太多,这篇文章首先介绍 JVM 类初始化的机制,然后给出几个易出错的实例来分析,帮助大家更好理解这个知识点。 JVM 将字节码转化为运行时对象分为三个阶段,分别是:loading 、Linking、initialization

Spring Security 基于表达式的权限控制

前言 spring security 3.0已经可以使用spring el表达式来控制授权,允许在表达式中使用复杂的布尔逻辑来控制访问的权限。 常见的表达式 Spring Security可用表达式对象的基类是SecurityExpressionRoot。 表达式描述hasRole([role])用户拥有制定的角色时返回true (Spring security默认会带有ROLE_前缀),去

浅析Spring Security认证过程

类图 为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类 概述 核心验证器 AuthenticationManager 该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数; public interface AuthenticationManager {Authentication authenticate(Authenti

Spring Security--Architecture Overview

1 核心组件 这一节主要介绍一些在Spring Security中常见且核心的Java类,它们之间的依赖,构建起了整个框架。想要理解整个架构,最起码得对这些类眼熟。 1.1 SecurityContextHolder SecurityContextHolder用于存储安全上下文(security context)的信息。当前操作的用户是谁,该用户是否已经被认证,他拥有哪些角色权限…这些都被保

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

Java架构师知识体认识

源码分析 常用设计模式 Proxy代理模式Factory工厂模式Singleton单例模式Delegate委派模式Strategy策略模式Prototype原型模式Template模板模式 Spring5 beans 接口实例化代理Bean操作 Context Ioc容器设计原理及高级特性Aop设计原理Factorybean与Beanfactory Transaction 声明式事物

中文分词jieba库的使用与实景应用(一)

知识星球:https://articles.zsxq.com/id_fxvgc803qmr2.html 目录 一.定义: 精确模式(默认模式): 全模式: 搜索引擎模式: paddle 模式(基于深度学习的分词模式): 二 自定义词典 三.文本解析   调整词出现的频率 四. 关键词提取 A. 基于TF-IDF算法的关键词提取 B. 基于TextRank算法的关键词提取

使用SecondaryNameNode恢复NameNode的数据

1)需求: NameNode进程挂了并且存储的数据也丢失了,如何恢复NameNode 此种方式恢复的数据可能存在小部分数据的丢失。 2)故障模拟 (1)kill -9 NameNode进程 [lytfly@hadoop102 current]$ kill -9 19886 (2)删除NameNode存储的数据(/opt/module/hadoop-3.1.4/data/tmp/dfs/na

Hadoop数据压缩使用介绍

一、压缩原则 (1)运算密集型的Job,少用压缩 (2)IO密集型的Job,多用压缩 二、压缩算法比较 三、压缩位置选择 四、压缩参数配置 1)为了支持多种压缩/解压缩算法,Hadoop引入了编码/解码器 2)要在Hadoop中启用压缩,可以配置如下参数