java线程学习之notify方法和notifyAll方法
notify(通知)方法,会将等待队列中的一个线程取出。比如obj.notify();那么obj的等待队列中就会有一个线程选中并且唤醒,然后被唤醒的队列就会退出等待队列。活跃线程调用等待队列中的线程时,因为现在的活跃线程还用有锁,会先将synchronized代码块执行完毕,释放对象监视器,被唤醒的线程才会获得这个监视器,然后被唤醒的线程才能继续执行。也就是说原来在等待队列中的线程被唤醒后,在被执行notify的一瞬间并不会立刻执行,因为在被执行notify的一瞬间,原来执行notify的线程还持有着锁,所以其他线程还无法获取这个实例的锁。
举个例子:假设熊大和熊二都要到小黑屋里面壁十分钟,小黑屋同一时刻只能允许一只熊进行面壁思过。熊大先进开始面壁思过同时把门锁上(相当于执行synchronized代码块拥有锁),结果在熊大面壁到三分钟的时候,困了想去睡觉(相当于执行wait()方法,进去到等待队列),这时它走出了门(相当于释放锁)去睡觉,熊二开始进来进行面壁思过,当熊二面壁到6分钟的时候,喊了一声让熊大接着来面壁思过(相当于执行notify方法),因为熊二还在继续面壁思过,所以熊大要在小黑屋外一直等,等到熊二面壁结束后(释放了锁),才能进去接着面壁,面壁剩余的七分钟,所以说即使熊二在第6分钟叫醒了熊大,但因为此时熊二在小黑屋里,熊大也不可能第一时间面壁思过。
如果说等待队列中的线程不止一个,那么当执行notify的时候叫醒那一个呢,被唤醒的线程是随机选择的。那么被唤醒的线程在作为锁定此对象的下一个线程方面没有可靠的特权或劣势。
notifyAll(通知全部)方法是将等待队列中的所以线程都唤醒,用法和notify一样。区别是notify只能唤醒等待队列中的一个,而notifyAll却能唤醒等待队列中的全部。
在实际使用时,是使用notify还是notifyAll,那个更好呢。
因为notify唤醒的线程比notifyAll少,所以notify的处理速度会更快。
使用notifyAll的代码要比使用notify的代码更健壮,因为使用notify如果处理不好,程序便有可能终止。
wait() ,notify()和notifyAll()方法都要获得此对象的监视器,也就是要获得锁,否则会报IllegalMonitorStateException异常
java线程学习之notify方法和notifyAll方法的更多相关文章
- Object类中wait代餐方法和notifyAll方法和线程间通信
Object类中wait代餐方法和notifyAll方法 package com.yang.Test.ThreadStudy; import lombok.SneakyThrows; /** * 进入 ...
- java数组、java.lang.String、java.util.Arrays、java.lang.Object的toString()方法和equals()方法详解
public class Test { public static void main(String[] args) { int[] a = {1, 2, 4, 6}; int[] b = a; in ...
- JAVA反射中的getFields()方法和getDeclaredFields ()方法的区别
JAVA反射中的getFields()方法和getDeclaredFields ()方法的区别 关于获取类的字段有两种方式:getFields()和getDeclaredFields().我们先来 ...
- Object类中wait带参方法和notifyAll方法和线程间通信
notifyAll方法: 进入到Timed_Waiting(计时等待)状态有两种方式: 1.sleep(long m)方法,在毫秒值结束之后,线程睡醒,进入到Runnable或BLocked状态 2. ...
- Java Thread中,run方法和start方法的区别
两种方法的区别: 1.start方法 用 start方法来启动线程,是真正实现了多线程, 通过调用Thread类的start()方法来启动一个线程,这时此线程处于就绪(可运行)状态,并没有运行,一旦 ...
- [转]JAVA反射中的getFields()方法和getDeclaredFields ()方法的区别
关于获取类的字段有两种方式:getFields()和getDeclaredFields().我们先来看看这两者的区别吧: getFields():获得某个类的所有的公共(public)的字段,包括父类 ...
- java.util.Scanner中hasNext()方法和next()方法的区别
先说结论: 两者均根据空格划分数据 两者在没有数据输入时均会等待输入 next()方法会将空格划分的数据依次输出,运行一次,输出一个 hasNext()方法会跟着next()方法移动,当前数据不为空, ...
- Java中Scanner中nextLine()方法和next()方法的区别
https://blog.csdn.net/hello_word2/article/details/54895106
- Object、String、数组的 toString() 方法和 equals() 方法及java.util.Arrays
public class Test { public static void main(String[] args) { int[] a = {1, 2, 4, 6}; int[] b = a; in ...
随机推荐
- Docker简介以及使用docker搭建lnmp的过程(多PHP版本)
一.Docker基础 Docker安装 Docker 要求 Ubuntu 系统的内核版本高于 3.10 ,查看本页面的前提条件来验证你的 Ubuntu 版本是否支持 Docker. 通过 uname ...
- C# WinForm:无法访问已释放的对象
C#在父窗口中调用子窗口的过程: 1. 创建子窗口对象 2. 显示子窗口对象 笔者的程序中,主窗体MainFrm通过菜单调用子窗口ChildFrm.在窗体中定义了子窗口对象,然后在菜单项点击事件中 ...
- char
1 char是多少位的 2 java用的是什么方式表示字符 3 Unicode是用多少位表示的 1的答案是16位的,2的答案是Unicode,3的答案是16位 值得注意的是,2的答案并不是utf-8 ...
- vue 实现子向父传值
父组件 <template> <div id="app"> <child @onChange='onChildValue'></child ...
- [dev][socket] unix domain socket删除socket文件
问题 在使用unix domain socket的时候,bind之后,会在本地路径里 产生一个与path对应的socket文件. 如何正确的在用完socket之后,对其销毁呢? 方案 使用 unlin ...
- npm 使用指南参考
[阮一峰npm scripts基本教程] [rimraf 跨平台删除文件] [ts-loader 安装问题] [nvm 安装使用] [npm镜像的问题] [webpack 如何引入jquery]web ...
- Redis集群概述
Redis Cluster与Redis3.0.0同时发布,以此结束了Redis无官方集群方案的时代,目前,Redis已经发布了3.0.7版本. redis cluster是去中心化,去中间件的,也就是 ...
- 导出CityGML
通过代码实现了导出CityGML功能
- Linux下Netty实现高性能UDP服务(SO_REUSEPORT)
参考: https://www.jianshu.com/p/61df929aa98b SO_REUSEPORT学习笔记:http://www.blogjava.net/yongboy/archive/ ...
- Spark SQL 编程初级实践
一.实验目的 (1) 通过实验掌握 Spark SQL 的基本编程方法: (2) 熟悉 RDD 到 DataFrame 的转化方法: (3) 熟悉利用 Spark ...