wait()和notify()是直接隶属于Object类,也就是说,所有对象都拥有这一对方法。初看起来这十分 不可思议,但是实际上却是很自然的,因为这一对方法阻塞时要释放占用的锁,而锁是任何对象都具有的,调用任意对象的 wait() 方法导致线程阻塞,并且该对象上的锁被释放。而调用任意对象的notify()方法则导致因调用该对象的wait() 方法而阻塞的线程中随机选择的一个解除阻塞(但要等到获得锁后才真正可执行)。

其次,wait()和notify()可在任何位置调用,但是这一对方法却必须在 synchronized 方法或块中调用,理由也很简单,只有在 synchronized 方法或块中当前线程才占有锁,才有锁可以释放。同样的道理,调用这一对方法的对象上的锁必须为当前线程所拥有,这样才有锁可以 释放。因此,方法调用必须放置在这样的 synchronized 方法或块中,该方法或块的加锁对象就是调用这些方法的对象。若不满足这一条 件,则程序虽然仍能编译,但在运行时会出现IllegalMonitorStateException 异常。
wait() 和 notify() 方法的上述特性决定了它们经常和synchronized 方法或块一起使用,将它们和操作系统的进程间通信机制作 一个比较就会发现它们的相似性:synchronized方法或块提供了类似于操作系统原语的功能,它们的执行不会受到多线程机制的干扰,而这一对方法则 相当于 block 和wakeup 原语(这一对方法均声明为 synchronized)。它们的结合使得我们可以实现操作系统上一系列精妙的进程间 通信的算法(如信号量算法),并用于解决各种复杂的线程间通信问题。
关于 wait() 和 notify() 方法最后再说明两点:
第一:调用 notify() 方法导致解除阻塞的线程是从因调用该对象的 wait() 方法而阻塞的线程中随机选取的,我们无法预料哪一个线程将会被选择,所以编程时要特别小心,避免因这种不确定性而产生问题。
第二:除了 notify(),还有一个方法 notifyAll() 也可起到类似作用,唯一的区别在于,调用 notifyAll() 方法将把因调 用该对象的 wait() 方法而阻塞的所有线程一次性全部解除阻塞。当然,只有获得锁的那一个线程才能进入可执行状态。
相关wait和notify使用demo:
01 /**
02  * <pre>
03  * 子线程循环10次,接着主线程循环100次,接着有回到子线程循环10次,
04  * 接着再回到主线程循环100次,如此执行50次
05  * </pre>
06  * @author ketqi
07  */
08 public class WaitNotifyDemo {
09     public static void main(String[] args) {
10 
11         final Business business = new Business();
12         new Thread(new Runnable() {
13             @Override
14             public void run() {
15                 for (int i = 1; i <= 50; i++) {
16                     business.sub(i);
17                 }
18 
19             }
20         }).start();
21 
22         for (int i = 1; i <= 50; i++) {
23             business.main(i);
24         }
25     }
26 }
27 
28 class Business {
29     private boolean isMainThread = true;
30 
31     public synchronized void sub(int i) {
32         while (!isMainThread) {
33             try {
34                 this.wait();
35             } catch (InterruptedException e) {
36                 e.printStackTrace();
37             }
38         }
39         for (int j = 1; j <= 10; j++) {
40             System.out.println("sub thread sequence of " + j + ",loop of " + i);
41         }
42         isMainThread = false;
43         this.notify();
44     }
45 
46     public synchronized void main(int i) {
47         while (isMainThread) {
48             try {
49                 this.wait();
50             } catch (InterruptedException e) {
51                 e.printStackTrace();
52             }
53         }
54         for (int j = 1; j <= 100; j++) {
55             System.out.println("main thread sequence of " + j + ",loop of " + i);
56         }
57         isMainThread = true;
58         this.notify();
59     }
60 }

转载于:https://blog.51cto.com/ketqi/1046825

java线程wait和notify详解相关推荐

  1. java线程池ThreadPoolExecutor类详解

    线程池有哪些状态 1. RUNNING:  接收新的任务,且执行等待队列中的任务 Accept new tasks and process queued tasks  2. SHUTDOWN: 不接收 ...

  2. java 线程一直运行状态_详解JAVA 线程-线程的状态有哪些?它是如何工作的?

    线程(Thread)是并发编程的基础,也是程序执行的最小单元,它依托进程而存在. 一个进程中可以包含多个线程,多线程可以共享一块内存空间和一组系统资源,因此线程之间的切换更加节省资源.更加轻量化,也因 ...

  3. 【Java多线程】Java线程状态及转换方法详解

    文章目录 1. 现代操作系统中的线程状态及转换(5种) 2. Java 线程状态(6种) 2.1 NEW 创建 2.2 RUNNABLE 运行 2.3 BLOCKED 阻塞 2.4 WAITING 等 ...

  4. Java线程6个状态详解

    文章目录 1. 概述 2. 举例说明 2.1 NEW 2.2 RUNNABLE 2.3 BLOCKED 2.4 WAITING 2.5 TIMED_WAITING 2.6 TERMINATED 1. ...

  5. Java线程池七大参数详解和配置

    目录 一.corePoolSize核心线程数 二.maximunPoolSize最大线程数 三.keepAliveTime空闲线程存活时间 四.unit空闲线程存活时间的单位 五.workQueue线 ...

  6. Java线程生产者消费者问题详解

    问题描述         生产者消费者问题(Producer-consumer problem),也称有限缓冲问题(Bounded-buffer problem),是一个多线程同步问题的经典案例.生产 ...

  7. Java线程安全的集合详解

    一.早期线程安全的集合 我们先从早期的线程安全的集合说起,它们是Vector和HashTable 1.Vector Vector和ArrayList类似,是长度可变的数组,与ArrayList不同的是 ...

  8. java线程和内核线程的,Java中内核线程理论及实例详解

    1.概念 内核线程是直接由操作系统内核控制的,内核通过调度器来完成内核线程的调度并负责将其映射到处理器上执行.内核态下的线程执行速度理论上是最高的,但是用户不会直接操作内核线程,而是通过内核线程的接口 ...

  9. 并发编程五:java并发线程池底层原理详解和源码分析

    文章目录 java并发线程池底层原理详解和源码分析 线程和线程池性能对比 Executors创建的三种线程池分析 自定义线程池分析 线程池源码分析 继承关系 ThreadPoolExecutor源码分 ...

最新文章

  1. DMS是临时解决方案?
  2. ICML 2021杰出论文奖“临时更换”,上海交大校友田渊栋陆昱成等获提名
  3. php python-浅谈php调用python文件
  4. js时间戳格式化成日期格式
  5. python switch_从邮箱验证小项目说python字符串判断与if判断那些事儿
  6. P4233-射命丸文的笔记【NTT,多项式求逆】
  7. 太阳直射点纬度计算公式_全纬度昼夜长短通用公式
  8. 学习JavaScript需要什么基础?
  9. LeetCode Week 5:第 41 ~ 50 题
  10. mysql一列数据转为一行_最最完整的 MySQL 规范都在这了
  11. nokia 3030 java 应用_诺基亚3030怎么样 :诺基亚3030测评【图解】
  12. 机器学习代码实战——PCA(主成分分析)
  13. ps制作哈7海报字体
  14. 抱米花豆丁下载器20100529(单文件绿色版)
  15. 电脑卡怎么办?4招帮你解决电脑卡顿的烦恼!
  16. 女生转行做什么工作好?想要转行互联网可以选择哪些方向?
  17. 拉流与推流的区别_RTSP协议交互流程之推流分析
  18. 如何理解结构化、非结构化和半结构化数据?
  19. 可以计算亲戚关系的超级计算器!
  20. 互联网上下50年,万字长文推演Web1.0到Web5.0

热门文章

  1. c语言课程设计做科普,【图片】发几个C语言课程设计源代码(恭喜自己当上技术小吧主)【东华理工大学吧】_百度贴吧...
  2. 计算机科学与技术专业的英文作文,计算机专业英语:科技交流与科技论文写作...
  3. 目前大多数个人计算机中可配置,2018年自考《计算机组成原理》试题五
  4. 移动端html右滑空白,BootStrap.css 在手机端滑动时右侧出现空白的原因及解决办法...
  5. mysql原生sql语句_原生SQL语句
  6. MapReduce框架下的FP Growth算法详解
  7. 手机qqsendencpac文件能删吗_无需任何app,手机电脑之前也能轻松传文件
  8. 人脸对齐(八)--LBF算法
  9. 人脸验证(三)--FaceNet
  10. 汇编学习--7.16--端口