看到一道面试题,写一个多线程程序,交替输出1、2、1、2……

  先写下程序:

/**
* Created by Andrew on 2015/10/28.
*/
public class OutputThread implements Runnable { private int num;
private Object lock; public OutputThread(int num,Object obj){
this.num = num;
this.lock = obj;
} @Override
public void run() {
try{
while(true) {
synchronized (lock){
lock.notifyAll();
lock.wait();
System.out.println(num);
} }}catch (Exception e){
e.printStackTrace();
}
} public static void main(String[] args) {
final Object obj = new Object();
Thread thread1 = new Thread(new OutputThread(0,obj));
Thread thread2 = new Thread(new OutputThread(1,obj)); thread1.start();
thread2.start(); }
}

然后用JDK1.8文档来解释下这两个方法:

wait()

Causes the current thread to wait until another thread invokes the notify() method or the notifyAll() method for this object.
The current thread must own this object's monitor.

This method causes the current thread (call it T) to place itself in the wait set for this object and then to relinquish any and all synchronization claims on this object. Thread T becomes disabled for thread scheduling purposes and lies dormant until one of four things happens:

  • Some other thread invokes the notify method for this object and thread T happens to be arbitrarily chosen as the thread to be awakened.
  • Some other thread invokes the notifyAll method for this object.
  • Some other thread interrupts thread T.
  • The specified amount of real time has elapsed, more or less. If timeout is zero, however, then real time is not taken into consideration and the thread simply waits until notified.
 

Throws:
IllegalMonitorStateException - if the current thread is not the owner of the object's monitor.
InterruptedException - if any thread interrupted the current thread before or while the current thread was waiting for a notification. The interrupted status of the current thread is cleared when this exception is thrown.

notifyAll()

Wakes up all threads that are waiting on this object's monitor.
 
The awakened threads will not be able to proceed until the current thread relinquishes the lock on this object. The awakened threads will compete in the usual manner with any other threads that might be actively competing to synchronize on this object; for example, the awakened threads enjoy no reliable privilege or disadvantage in being the next thread to lock this object.
 

Throws:
IllegalMonitorStateException - if the current thread is not the owner of this object's monitor.

  

notify

Wakes up a single thread that is waiting on this object's monitor. If any threads are waiting on this object, one of them is chosen to be awakened. The choice is arbitrary and occurs at the discretion of the implementation. A thread waits on an object's monitor by calling one of the wait methods.

Throws:
IllegalMonitorStateException - if the current thread is not the owner of this object's monitor.

中文文档:

  首先,调用wait()的前提是,当前线程A拥有该对象的锁,否则调用wait()时会抛出IllegalMonitorStateException  。wait() 会使得当前线程A进入该对象的等待列表,并释放锁,直到发生下面的任何事情之一:

  • 别的线程调用notify(),而线程A碰巧是JVM选择唤醒的那个
  • 别的线程调用notifyAll()
  • 其他线程中断了线程A
  • wait(time)超过了时间限定

  调用notifyAll()则会使得所有等待该对象锁的线程被唤醒,去竞争这个对象锁。与notify()的区别是,前者会唤醒所有等待该对象锁的线程,后者则把选择权交给JVM。

  接下来解释程序逻辑。

  假设线程A先进入同步代码块儿

while(true) {
      synchronized (lock){
lock.notifyAll();
lock.wait();
System.out.println(num);
}
}
  1. A调用lock.notifyAll()唤醒所有等待lock锁的线程,然而这时A还持有锁,B线程都进不来。
  2. A调用lock.wait()时,A进入lock对象的等待列表,并释放lock锁。
  3. 此时B已经在同步块儿外面等候多时,迫不及待地进入。
  4. B调用lock.notifyAll(),根据API说明,直到当前线程放弃此对象上的锁定,才能继续执行被唤醒的线程所以B线程继续执行
  5. B调用lock.wait(),B进入lock对象的等待列表,并释放lock锁。
  6. A作为被唤醒的线程,进入同步代码块,继续从wait()往下执行,打印num,while(true)循环重新进入同步块
  7. A调用lock.notifyAll()唤醒所有等待lock锁的线程,然而这时A还持有锁,B线程都进不来。
  8. A调用lock.wait()时,A进入lock对象的等待列表,并释放lock锁。
  9. B作为被唤醒的线程,进入同步代码块,继续从wait()往下执行,打印num,while(true)循环重新进入同步块

   ……

  流程就是这么个流程,通过这个小例子对wait()、notify()和notifyAll()进行理解吧。

  

  

  

notify()、notifyAll()和wait()的更多相关文章

  1. java 多线程之wait(),notify,notifyAll(),yield()

    wait(),notify(),notifyAll()不属于Thread类,而是属于Object基础类,也就是说每个对像都有wait(),notify(),notifyAll()的功能.因为都个对像都 ...

  2. java中的wait(),notify(),notifyAll(),synchronized方法

    wait(),notify(),notifyAll()三个方法不是Thread的方法,而是Object的方法.意味着所有对象都有这三个方法,因为每个对象都有锁,所以自然也都有操作锁的方法了.这三个方法 ...

  3. java 多线程(wait/notify/notifyall)

    package com.example; public class App { /* wait\notify\notifyAll 都属于object的内置方法 * wait: 持有该对象的线程把该对象 ...

  4. Java多线程8:wait()和notify()/notifyAll()

    轮询 线程本身是操作系统中独立的个体,但是线程与线程之间不是独立的个体,因为它们彼此之间要相互通信和协作. 想像一个场景,A线程做int型变量i的累加操作,B线程等待i到了10000就打印出i,怎么处 ...

  5. 使用Object的wait,notify,notifyAll做线程调度

    我们知道java中的所有类的祖先都是Object,Object类有四个个方法wait(),wait(long timeout),notify(),notifyAll(),这四个方法可以用来做线程的调度 ...

  6. Java多线程之wait(),notify(),notifyAll()

    在多线程的情况下,因为同一进程的多个线程共享同一片存储空间,在带来方便的同一时候,也带来了訪问冲突这个严重的问题.Java语言提供了专门机制以解决这样的冲突,有效避免了同一个数据对象被多个线程同一时候 ...

  7. Java多线程的wait(),notify(),notifyAll()

    在多线程的情况下.因为多个线程与存储空间共享相同的过程,同时带来的便利.它也带来了访问冲突这个严重的问题. Java语言提供了一种特殊的机制来解决这类冲突,避免同一数据对象由多个线程在同一时间访问. ...

  8. Java多线程学习之wait、notify/notifyAll 详解

    1.wait().notify/notifyAll() 方法是Object的本地final方法,无法被重写. 2.wait()使当前线程阻塞,前提是 必须先获得锁,一般配合synchronized 关 ...

  9. 【java线程系列】java线程系列之线程间的交互wait()/notify()/notifyAll()及生产者与消费者模型

    关于线程,博主写过java线程详解基本上把java线程的基础知识都讲解到位了,但是那还远远不够,多线程的存在就是为了让多个线程去协作来完成某一具体任务,比如生产者与消费者模型,因此了解线程间的协作是非 ...

  10. Java多线程:wait(),notify(),notifyAll()

    1. wait(),notify(),notifyAll() 2. wait() 2.1. wait() 2.2. wait(long timeout) 2.3. wait(long timeout, ...

随机推荐

  1. 校园招聘 - 比較easy的面试题

    又到校园招聘的季节了, 自从和一些同事出版了<编程之美>一书之后, 我常常收到一些关于面试, 编程,  和"题库"的询问. 事实上我自己对算法没有什么研究, 有些问题都 ...

  2. frame.origin.x 的意思和作用?

    frame.origin.x 的意思和作用? scrollView.frame 一个view的frame 包含它的矩形形状(size)的长和宽. 和它在父视图中的坐标原点(origin)x和y坐标 f ...

  3. BootStrap 智能表单系列 九 表单图片上传的支持

    本章介绍如何在生成表单后,可以支持上传图片后可以及时预览图片 代码如下(连接地址:https://github.com/xiexingen/Bootstrap-SmartForm/blob/maste ...

  4. 简单的web三层架构系统【第三版】

    今天是第三版,和前几天一样今天还是要对代码进行优化,三层架构是一种思想,具体能不能使得整个系统安全和高性能,还是要看代码编写的是否合理,逻辑性是否严谨. 昨天偶然间看到别人写的三层架构中,竟然没有在方 ...

  5. Random类短时间大量随机重复的问题

    先声明一下,我是在那篇文章上看到的解决方法: http://dl.download.csdn.net/down10/20141103/4b173214e41ff3207305c2470524b0f3. ...

  6. c++之构造函数学习

    #include<stdio.h> class Test {      private:      int i;      int j;      int k;     public :  ...

  7. java 去除数组重复数据,并输出重复数据值

    /** * 去除重复数据 * @author Sunqinbo */ public class RemoveDuplicateData { public static void main(String ...

  8. 远程连接MySQL 不允许

    报错:1130-host ... is not allowed to connect to this MySql server 1. 改表法. 可能是你的帐号不允许从远程登陆,只能在localhost ...

  9. 【转】IOS 输入框被键盘遮盖的解决方法

    做IOS开发时,难免会遇到输入框被键盘遮掩的问题.上网上搜索了很多相关的解决方案,看了很多,但是由衷的觉得太麻烦了. 有的解决方案是将视图上的所有的东西都添加到一个滚动视图对象( UIScrollVi ...

  10. 模拟美萍加密狗--Rockey2虚拟狗(三)

    几经挣扎,我最终还是选择了虚拟设备的方法来模拟Rockey2加密狗.HID.DLL劫持+API劫持的办法技术上虽然简单些,但太繁琐了,不仅要转发大量的函数,还要Hook好几个API,向我这么懒的人可干 ...