博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
wait、notify、notifyAll的阻塞和恢复
阅读量:7197 次
发布时间:2019-06-29

本文共 2987 字,大约阅读时间需要 9 分钟。

(一)准备

  按照惯例应该是要先介绍一下wait、notify和notifyAll的基础知识。我找到了一篇不错的文章:《》,它甚至介绍了为什么wait等方法为什么必须先获得对象锁。在这里我就不重复说了。

(二)阻塞和恢复

(1)wait方法

  wait方法继承自Object类(方法修饰符为fianl ,这也解释了为什么condition类中不能重写wait等方法),一共有三个方法:

public final void wait(long timeout)                 throws InterruptedException public final void wait(long timeout, int nanos) throws InterruptedException public final void wait() throws InterruptedException

  阻塞:这三个方法的调用都会使当前线程阻塞。该线程将会被放置到对该Object的请求等待队列中,然后让出当前对Object所拥有的所有的同步请求。线程会一直暂停所有线程调度,直到下面其中一种情况发生:

    ① 其他线程调用了该Object的notify方法,而该线程刚好是那个被唤醒的线程;

    ② 其他线程调用了该Object的notifyAll方法;

    ③ 其他对象中断/杀死了该线程;

    ④ (这种情况,只针对前两个方法)线程在等待指定的时间后;

  恢复:线程将会从等待队列中移除,重新成为可调度线程。它会与其他线程以常规的方式竞争对象同步请求。一旦它重新获得对象的同步请求,所有之前的请求状态都会恢复,也就是线程调用wait的地方的状态。线程将会在之前调用wait的地方继续运行下去。

(2)notify和notifyAll方法

  notify的作用就是唤醒请求队列中的一个线程,而notifyAll唤醒的是请求队列中的所有线程。

  被唤醒的线程不会马上运行,除非获取了该Object的锁。也就是说,调用notify的线程,在调用notify后,不会像wait一样,马上阻塞线程的运行。而是继续运行,直到相应的线程调度完成或者让出Object的锁。而被唤醒的线程会在当前线程让出Object锁后,与其他线程以常规的方式竞争对象锁(正如上面提到的)。

 

参考资料:

https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html

public class WaitNotifyDemo {    private volatile int val = 1;    private Object o1= new Object();    private Object o2= new Object();    public class PrinterA implements Runnable {        public void run() {            while (val <= 3) {                synchronized (o2) {                    try {                        System.out.println("222222222");                        o2.wait();                        System.out.println("111111111");                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                }            }        }    }    public class PrinterC implements Runnable {        public void run() {            while (val <= 3) {                synchronized (o2) {                    try {                        System.out.println("4444");                        o2.wait();                        System.out.println("3333");                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                }            }        }    }    public class PrinterB implements Runnable {        public void run() {            while (val <= 30000) {                synchronized (o2) {                    o2.notify();//                    o2.notifyAll();                }            }        }    }    public static void main(String[] args) {        WaitNotifyDemo demo = new WaitNotifyDemo();        demo.doPrint();    }    private void doPrint() {        PrinterA pa = new PrinterA();        Thread a = new Thread(pa);        a.setName("printerA");        a.start();        PrinterC pc = new PrinterC();        Thread c = new Thread(pc);        c.setName("printerC");        c.start();        PrinterB pB = new PrinterB();        Thread b = new Thread(pB);        b.setName("printerA");        b.start();    }}

 

本文转自农夫山泉别墅博客园博客,原文链接:http://www.cnblogs.com/yaowen/p/6141807.html,如需转载请自行联系原作者

你可能感兴趣的文章
FreeMarker标签
查看>>
AngularJS 中的 Promise 和 设计模式
查看>>
《从面试题来看源码》,单参数,多参数,如何正确使用@Param
查看>>
《JavaScript设计模式》学习日志
查看>>
MySql 建表、添加字段、修改字段、添加索引SQL语句写法
查看>>
Core Bluetooth框架之三:最佳实践
查看>>
Gson序列化时@SerializedName的使用
查看>>
windows上pip install 报编码错误
查看>>
boost asio学习笔记 [1] - 同步通讯
查看>>
什么是BMC商业模式?
查看>>
不同浏览器中单选框和文字对齐的兼容
查看>>
Python 浮点数在列表中排序的问题
查看>>
一个失业三年后,又重新找回自信的小伙靠的是什么?
查看>>
JFinal学习-Excel导出
查看>>
linuxbridge 小贴士
查看>>
红旗inWise操作系统V8.0发布了!!!
查看>>
tiles2
查看>>
vi 合并多个文件
查看>>
切换npm源
查看>>
关于Linux静态库和动态库的分析
查看>>