wait()/ notify()/ notifyAll()

任何Object对象都可以作为这三个方法的主调,但是不推荐线程对象调用这些方法。

1使用wait()、notify()和notifyAll()时需要首先对调用对象加锁【必须使用在同步代码块】
2调用wait()方法后,线程状态会从RUNNING变为WAITING,并将当线程加入到lock对象的等待队列中【会释放锁】 ,后面的代码就不执行了 。当被唤醒并被执行时,是接着上次执行到的wait()方法代码后面继续往下执行的。
3调用notify()或者notifyAll()方法后,等待在lock对象的等待队列的线程不会马上从wait()方法返回,必须要等到调用notify()或者notifyAll()方法的线程将lock锁释放,等待线程才有机会从等待队列返回。这里只是有机会,因为锁释放后,等待线程会出现竞争,只有竞争到该锁的线程才会从wait()方法返回,其他的线程只能继续等待

下面代码演示

public class WaitNotifyThread {
//条件是否满足的标志
private static boolean flag = true;
//对象的监视器锁
private static Object lock = new Object(); public static void main(String[] args){
Thread waitThread = new Thread(new WaitThread(),"WaitThread");
waitThread.start(); Thread notifyThread = new Thread(new NotifyThread(),"NotifyThread");
notifyThread.start();
} /**
* 等待线程
*/
private static class WaitThread implements Runnable{
public void run() {
//加锁,持有对象的监视器锁
synchronized (lock){
//只有成功获取对象的监视器才能进入这里
//当条件不满足的时候,继续wait,直到某个线程执行了通知
//并且释放了lock的监视器(简单来说就是锁)才能从wait
//方法返回
while (flag){
try {
System.out.println(Thread.currentThread().getName() + " flag is true"
);
lock.wait(); //相当于睡眠 但是释放锁的
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//条件满足,继续工作
System.out.println(Thread.currentThread().getName() + " flag is false "
);
}
}
} /**
* 通知线程
*/
private static class NotifyThread implements Runnable{
public void run() {
synchronized (lock){
//获取lock锁,然后执行通知,通知的时候不会释放lock锁
//只有当前线程退出了lock后,waitThread才有可能从wait返回
System.out.println(Thread.currentThread().getName() + " holds lock "
);
lock.notifyAll(); //唤醒wait 但是只有释放代码块以后 wait变成就绪
flag = false;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//再次加锁
synchronized (lock){
System.out.println(Thread.currentThread().getName() + " holds lock again "
);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}

  运行结果会有两种

或者

这个例子只是想说明 调用notify 或者notifyAll 并不会释放锁 要等到同步代码执行完成以后 才会释放  释放以后,两个线程的执行是不确定的

所以会有2个结果

Java多线程系列4 线程交互(wait和notify方法)的更多相关文章

  1. Java多线程系列--“JUC线程池”06之 Callable和Future

    概要 本章介绍线程池中的Callable和Future.Callable 和 Future 简介示例和源码分析(基于JDK1.7.0_40) 转载请注明出处:http://www.cnblogs.co ...

  2. Java多线程系列--“JUC线程池”02之 线程池原理(一)

    概要 在上一章"Java多线程系列--“JUC线程池”01之 线程池架构"中,我们了解了线程池的架构.线程池的实现类是ThreadPoolExecutor类.本章,我们通过分析Th ...

  3. Java多线程系列--“JUC线程池”03之 线程池原理(二)

    概要 在前面一章"Java多线程系列--“JUC线程池”02之 线程池原理(一)"中介绍了线程池的数据结构,本章会通过分析线程池的源码,对线程池进行说明.内容包括:线程池示例参考代 ...

  4. Java多线程系列--“JUC线程池”04之 线程池原理(三)

    转载请注明出处:http://www.cnblogs.com/skywang12345/p/3509960.html 本章介绍线程池的生命周期.在"Java多线程系列--“基础篇”01之 基 ...

  5. Java多线程系列--“JUC线程池”05之 线程池原理(四)

    概要 本章介绍线程池的拒绝策略.内容包括:拒绝策略介绍拒绝策略对比和示例 转载请注明出处:http://www.cnblogs.com/skywang12345/p/3512947.html 拒绝策略 ...

  6. Java多线程系列--“JUC线程池”01之 线程池架构

    概要 前面分别介绍了"Java多线程基础"."JUC原子类"和"JUC锁".本章介绍JUC的最后一部分的内容——线程池.内容包括:线程池架构 ...

  7. java多线程系列(六)---线程池原理及其使用

    线程池 前言:如有不正确的地方,还望指正. 目录 认识cpu.核心与线程 java多线程系列(一)之java多线程技能 java多线程系列(二)之对象变量的并发访问 java多线程系列(三)之等待通知 ...

  8. Java多线程系列 JUC线程池04 线程池原理解析(三)

    转载 http://www.cnblogs.com/skywang12345/p/3509954.html  https://blog.csdn.net/qq_22929803/article/det ...

  9. Java多线程系列 JUC线程池02 线程池原理解析(一)

    转载  http://www.cnblogs.com/skywang12345/p/3509960.html ; http://www.cnblogs.com/skywang12345/p/35099 ...

随机推荐

  1. MySQL查询不使用索引汇总 + 如何优化sql语句

    不使用索引原文 : http://itlab.idcquan.com/linux/MYSQL/918330.html MySQL查询不使用索引汇总 众所周知,增加索引是提高查询速度的有效途径,但是很多 ...

  2. SpringBoot Web开发(5) 开发页面国际化+登录拦截

    SpringBoot Web开发(5) 开发页面国际化+登录拦截 一.页面国际化 页面国际化目的:根据浏览器语言设置的信息对页面信息进行切换,或者用户点击链接自行对页面语言信息进行切换. **效果演示 ...

  3. .net updatePannel 局部刷新效果实现后,但是仍是全部刷新的修改方法

    最近做了一个小例子,就是晚上都有的那种小的updatepannel的局部刷新的小例子,但是发现按照那个例子虽然能够实现label2的局部刷新,但是看上去效果确实整个页面都在刷新,这让人很头疼,所以我在 ...

  4. 1131(★、※)Subway Map

    思路:DFS遍历 #include <iostream> #include <map> #include <vector> #include <cstdio& ...

  5. pytorch下的lib库 源码阅读笔记(2)

    2017年11月22日00:25:54 对lib下面的TH的大致结构基本上理解了,我阅读pytorch底层代码的目的是为了知道 python层面那个_C模块是个什么东西,底层完全黑箱的话对于理解pyt ...

  6. 减肥标准BMI指数

    原文: https://baike.baidu.com/item/BMI%E6%8C%87%E6%95%B0/4477882?fromtitle=%E4%BD%93%E9%87%8D%E6%8C%87 ...

  7. python3中的urllib.parse的常用方法

    将URL按一定的格式进行拆分 使用 urllib.parse.urlparse将url分为6个部分,返回一个包含6个字符串项目的元组:协议.位置.路径.参数.查询.片段 参照官方地址:https:// ...

  8. spring boot 错误处理之深度历险

    今天终于把 boot 的异常处理完全研究透了: boot提供了很多错误的处理工作.默认情况下,我们会看到一个whiteLabel(白标)的页面. 这个可能不是我们所需.因此我们需要定制.我于是做了个深 ...

  9. centos rz sz安装

    1.命令: yum install lrzsz 2.

  10. PHP判断手机、电脑访问

    /*判断用户是手机访问还是电脑访问*/$useragent = $_SERVER['HTTP_USER_AGENT']; if (preg_match('/(android|bb\d+|meego). ...