【本文转自】http://www.cnblogs.com/dolphin0520/p/3920385.html

这三个方法的文字描述可以知道以下几点信息:

  1)wait()、notify()和notifyAll()方法是本地方法,并且为final方法,无法被重写。

  2)调用某个对象的wait()方法能让当前线程阻塞,并且当前线程必须拥有此对象的monitor(即锁)

  3)调用某个对象的notify()方法能够唤醒一个正在等待这个对象的monitor的线程,如果有多个线程都在等待这个对象的monitor,则只能唤醒其中一个线程;

  4)调用notifyAll()方法能够唤醒所有正在等待这个对象的monitor的线程;

  有朋友可能会有疑问:为何这三个不是Thread类声明中的方法,而是Object类中声明的方法(当然由于Thread类继承了Object类,所以Thread也可以调用者三个方法)?其实这个问题很简单,由于每个对象都拥有monitor(即锁),所以让当前线程等待某个对象的锁,当然应该通过这个对象来操作了。而不是用当前线程来操作,因为当前线程可能会等待多个线程的锁,如果通过线程来操作,就非常复杂了。

  上面已经提到,如果调用某个对象的wait()方法,当前线程必须拥有这个对象的monitor(即锁),因此调用wait()方法必须在同步块或者同步方法中进行(synchronized块或者synchronized方法)。

  调用某个对象的wait()方法,相当于让当前线程交出此对象的monitor,然后进入等待状态,等待后续再次获得此对象的锁(Thread类中的sleep方法使当前线程暂停执行一段时间,从而让其他线程有机会继续执行,但它并不释放对象锁);

  notify()方法能够唤醒一个正在等待该对象的monitor的线程,当有多个线程都在等待该对象的monitor的话,则只能唤醒其中一个线程,具体唤醒哪个线程则不得而知。

  同样地,调用某个对象的notify()方法,当前线程也必须拥有这个对象的monitor,因此调用notify()方法必须在同步块或者同步方法中进行(synchronized块或者synchronized方法)。

  nofityAll()方法能够唤醒所有正在等待该对象的monitor的线程,这一点与notify()方法是不同的。

  这里要注意一点:notify()和notifyAll()方法只是唤醒等待该对象的monitor的线程,并不决定哪个线程能够获取到monitor。

  举个简单的例子:假如有三个线程Thread1、Thread2和Thread3都在等待对象objectA的monitor,此时Thread4拥有对象objectA的monitor,当在Thread4中调用objectA.notify()方法之后,Thread1、Thread2和Thread3只有一个能被唤醒。注意,被唤醒不等于立刻就获取了objectA的monitor。假若在Thread4中调用objectA.notifyAll()方法,则Thread1、Thread2和Thread3三个线程都会被唤醒,至于哪个线程接下来能够获取到objectA的monitor就具体依赖于操作系统的调度了。

  上面尤其要注意一点,一个线程被唤醒不代表立即获取了对象的monitor,只有等调用完notify()或者notifyAll()并退出synchronized块,释放对象锁后,其余线程才可获得锁执行。

下面看一个例子就明白了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
public class Test {
    public static Object object = new Object();
    public static void main(String[] args) {
        Thread1 thread1 = new Thread1();
        Thread2 thread2 = new Thread2();
         
        thread1.start();
         
        try {
            Thread.sleep(200);
        catch (InterruptedException e) {
            e.printStackTrace();
        }
         
        thread2.start();
    
     
    static class Thread1 extends Thread{
        @Override
        public void run() {
            synchronized (object) {
                try {
                    object.wait();
                catch (InterruptedException e) {
                }
                System.out.println("线程"+Thread.currentThread().getName()+"获取到了锁");
            }
        }
    }
     
    static class Thread2 extends Thread{
        @Override
        public void run() {
            synchronized (object) {
                object.notify();
                System.out.println("线程"+Thread.currentThread().getName()+"调用了object.notify()");
            }
            System.out.println("线程"+Thread.currentThread().getName()+"释放了锁");
        }
    }
}

  无论运行多少次,运行结果必定是:

线程Thread-1调用了object.notify()
线程Thread-1释放了锁
线程Thread-0获取到了锁

【转载】Java - Wait & Notify的更多相关文章

  1. [转载]Java中继承、装饰者模式和代理模式的区别

    [转载]Java中继承.装饰者模式和代理模式的区别 这是我在学Java Web时穿插学习Java设计模式的笔记 我就不转载原文了,直接指路好了: 装饰者模式和继承的区别: https://blog.c ...

  2. [转载]Java序列化与反序列化

    [转载]Java序列化与反序列化 来源: https://www.cnblogs.com/anitinaj/p/9253921.html 序列化和反序列化作为Java里一个较为基础的知识点,那你能说一 ...

  3. [转载]java中import作用详解

    [转载]java中import作用详解 来源: https://blog.csdn.net/qq_25665807/article/details/74747868 这篇博客讲的真的很清楚,这个作者很 ...

  4. [转载]Java中异常的捕获顺序(多个catch)

    http://blog.sina.com.cn/s/blog_6b022bc60101cdbv.html [转载]Java中异常的捕获顺序(多个catch) (2012-11-05 09:47:28) ...

  5. JAVA wait(), notify(),sleep具体解释

    在CSDN开了博客后,一直也没在上面公布过文章,直到前一段时间与一位前辈的对话,才发现技术博客的重要,立志要把CSDN的博客建好.但一直没有找到好的开篇的主题,今天再看JAVA线程相互排斥.同步的时候 ...

  6. [转载] Java实现生产者消费者问题

    转载自http://www.cnblogs.com/happyPawpaw/archive/2013/01/18/2865957.html 引言 生产者和消费者问题是线程模型中的经典问题:生产者和消费 ...

  7. [转载] java多线程总结(三)

    转载自: http://www.cnblogs.com/lwbqqyumidi/p/3821389.html 作者:Windstep 本文主要接着前面多线程的两篇文章总结Java多线程中的线程安全问题 ...

  8. [转载]java之yield(),sleep(),wait()区别详解

    原文地址:http://dylanxu.iteye.com/blog/1322066 1.sleep() 使当前线程(即调用该方法的线程)暂停执行一段时间,让其他线程有机会继续执行,但它并不释放对象锁 ...

  9. [转载]java int与integer的区别

    声明: 本篇文章属于转载文章,来源:

随机推荐

  1. Python 循环语句(break和continue)

    Python 循环语句(break和continue) while 语句时还有另外两个重要的命令 continue,break 来跳过循环,continue 用于跳过该次循环,break 则是用于退出 ...

  2. Python条件判断(if)

    Python条件判断(if) 一.基本介绍 1.Python 编程中 if 语句用于控制程序的执行,基本形式为: if 判断条件: 执行语句…… 需要注意的是,Python没有像其他大多数语言一样使用 ...

  3. MVC系统学习8——AsyncController

    关于为什么使用异步Controller,这里不做备忘,三岁小孩都懂.主要的备忘是如何使用AsyncController. //这个action以Async结尾,并且返回值是void public vo ...

  4. IDA-IDC脚本编写语法

    1.IDA脚本编写基础 IDC是IDA内置的脚本语言,其语法与C非常相似,它是一种解释性语言. 执行方法 在IDA中按SHIFT+F2键会弹出一个对话框,把语句直接写在对话框中,点击run就可被运行. ...

  5. 特种部队(codevs 1427)

    题目描述 Description 某特种部队接到一个任务,需要潜入一个仓库.该部队士兵分为两路,第一路士兵已经在正面牵制住了敌人,第二路士兵正在悄悄地从后方秘密潜入敌人的仓库.当他们到达仓库时候,发现 ...

  6. Delphi:校验手机号及身份证号

    //校验手机号  function IsMobileNumber( num:string ):boolean;   begin     Result:=False;     if length( tr ...

  7. Restful 级别划分以及HATEOAS是什么?

    Restful简介 Rest是一种软件架构风格.设计风格,而不是标准,只是提供了一组设计原则和约束条件.它主要用于客户端和服务器交互类的软件.基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存 ...

  8. [大雾雾雾雾] 告别该死的 EFCore Fluent API

    [EF Core Oracle  列名大小写问题] [EF Core Oracle column name case problem] [EF Core PostgreSql 列名大小写问题] [EF ...

  9. how to get geometry type of layer using IMapServer3 and IMapLayerInfo? (C#)

    http://forums.arcgis.com/threads/11481-how-to-get-geometry-type-of-layer-using-IMapServer3-and-IMapL ...

  10. Vue中-下拉框可以选择可以填写

    <el-form-item label="方法名称"> <el-autocomplete popper-class="my-autocomplete&q ...