Java 异步编程之:notify 和 wait 用法

栏目: Java · 发布时间: 6年前

内容简介:最近看帖子,发现一道面试题:启动两个线程, 一个输出 1,3,5,7…99, 另一个输出 2,4,6,8…100 最后 STDOUT 中按序输出 1,2,3,4,5…100题目要求用 Java 的 wait + notify 机制来实现,重点考察对于多线程可见性的理解。

最近看帖子,发现一道面试题:

启动两个线程, 一个输出 1,3,5,7…99, 另一个输出 2,4,6,8…100 最后 STDOUT 中按序输出 1,2,3,4,5…100

题目要求用 Java 的 wait + notify 机制来实现,重点考察对于多线程可见性的理解。

wait 和 notify 简介

wait 和 notify 均为 Object 的方法:

  • Object.wait() —— 暂停一个线程
  • Object.notify() —— 唤醒一个线程

从以上的定义中,我们可以了解到以下事实:

  • 想要使用这两个方法,我们需要先有一个 对象 Object。
  • 在多个线程之间,我们可以通过调用 同一个对象wait()notify() 来实现不同的线程间的可见。

对象控制权(monitor)

在使用 wait 和 notify 之前,我们需要先了解对象的控制权(monitor)。在 Java 中任何一个时刻,对象的控制权只能被一个线程拥有。如何理解控制权呢?请先看下面的简单代码:

public class ThreadTest {
    public static void main(String[] args) {
        Object object = new Object();
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    object.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }
}

直接执行,我们将会得到以下异常:

Exception in thread "Thread-0" java.lang.IllegalMonitorStateException
    at java.lang.Object.wait(Native Method)
    at java.lang.Object.wait(Object.java:502)
    at com.xiangyu.demo.ThreadTest$1.run(ThreadTest.java:10)
    at java.lang.Thread.run(Thread.java:748)

出错的代码在: object.wait(); 。这里我们需要了解以下事实:

  • 无论是执行对象的 wait、notify 还是 notifyAll 方法,必须保证当前运行的线程取得了该对象的控制权(monitor)
  • 如果在没有控制权的线程里执行对象的以上三种方法,就会报 java.lang.IllegalMonitorStateException 异常。
  • JVM 基于多线程,默认情况下不能保证运行时线程的时序性

在上面的示例代码中,我们 new 了一个 Thread,但是对象 object 的控制权仍在主线程里。所以会报 java.lang.IllegalMonitorStateException 。

我们可以通过同步锁来获得对象控制权,例如:synchronized 代码块。对以上的示例代码做改造:

public class ThreadTest {
    public static void main(String[] args) {
        Object object = new Object();
        new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (object){ // 修改处
                    try {
                        object.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
    }
}

再次执行,代码不再报错。

解题

了解了对象控制权之后,我们就可以正常地使用 notify 和 wait 了,下面给出我的解题方法,供参考。

public class ThreadTest {
    private final Object flag = new Object();

    public static void main(String[] args) {
        ThreadTest threadTest = new ThreadTest();
        ThreadA threadA = threadTest.new ThreadA();
        threadA.start();
        ThreadB threadB = threadTest.new ThreadB();
        threadB.start();
    }

    class ThreadA extends Thread {
        @Override
        public void run() {
            synchronized (flag) {
                for (int i = 0; i <= 100; i += 2) {
                    flag.notify();
                    System.out.println(i);
                    try {
                        flag.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }

        }
    }

    class ThreadB extends Thread {
        @Override
        public void run() {
            synchronized (flag) {
                for (int i = 1; i < 100; i += 2) {
                    flag.notify();
                    System.out.println(i);
                    try {
                        flag.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

创新者

创新者

[美] 沃尔特 · 艾萨克森 / 关嘉伟、牛小婧 / 中信出版社 / 2016-6 / 88.00

讲述了计算机和互联网从无到有的发展历程,并为我们生动地刻画出数字时代的创新者群像。 在近200年的数字化进程中群星闪耀,艾萨克森从一个计算机程序的创造者、诗人拜伦之女埃达说起,细数了这一群站在科学与人文交叉路口的创新者,他们包括通用型电子计算机的创造者奠奇利、科学家冯·诺依曼、仙童半导体公司的“八叛逆”、天才图灵、英特尔的格鲁夫、微软的比尔·盖茨、苹果公司的乔布斯、谷歌的拉里·佩奇等。《创新......一起来看看 《创新者》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器