Object类中有关线程通信的方法有两个notify方法和三个wait方法,官方解释:

void notify()

Wakes up a single thread that is waiting on this object's monitor.
void notifyAll()

Wakes up all threads that are waiting on this object's monitor.
String toString()

Returns a string representation of the object.
void wait()

Causes the current thread to wait until another thread invokes the notify() method or the notifyAll() method for this object.
void wait(long timeout)

Causes the current thread to wait until either another thread invokes the notify() method or the notifyAll() method for this object, or a specified amount of time has elapsed.
void wait(long timeout, int nanos)

Causes the current thread to wait until another thread invokes the notify() method or the notifyAll() method for this object, or some other thread interrupts the current thread, or a certain amount of real time has elapsed.

  这些方法都是final类型的,不能被子类重写。

  调用wait()和notify()方法的前提是,线程调用这两个方法时,拥有当前对象的monitor,即锁。所以,这两种方法的调用必须放在synchronized方法或synchronized块中。

  wait()与sleep()的比较:调用wait()后,当前线程失去了对象的monitor,必须被其他线程唤醒或设定的等待时间已超时,才能继续执行,并且被唤醒后,该线程并不会马上继续运行,而是放在线程就绪队列中,与其他线程公平竞争,获取对象的monitor。调用sleep()后,当前线程仍用够对象的monitor,当设定的睡眠时间超时后,线程会马上继续执行。

  一个线程变为一个对象的锁的拥有者,可以通过三种途径:

    1. 运行这个对象的synchronized的实例方法。
    2. 运行这个对象的synchronized的语句块。
    3. 对于Class类的对象,运行类的synchronized、static的方法。

假设有两个线程A和B公用一个NumberControl的类的对象,类结构如下:

public class NumberControl
{
private int number; public synchronized void increase()
{
if (0 != number)
{
try
{
wait();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
number++;
System.out.println(number);
notify();
} public synchronized void decrease()
{
if (0 == number)
{
try
{
wait();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
number--;
System.out.println(number);
notify();
}
}

NumberControl

  A线程执行对象的increase()方法,如果number为1,则线程等待。B线程执行对象的decrease()方法,如果number为0,则线程等待。然后执行A、B线程,得到的结果,number回程1、0、1、0的交替变化。

  但需要注意的是,如果在添加更过的线程共享这个对象,假设是4个线程A、B、C、D,A和C线程调用increase()方法,B和D线程调用decrease方法,再去试图让number得到1、0的交替变化,那当线程被唤醒后,仍需判断number的状态,是1还是0,因为在同一个对象中,当一个线程执行notify()时,被唤醒的线程是被随机挑选出来的。可能出现的情况是,B、C、D线程都处于等待状态,A状态执行完notify()方法,此时number是1,B、C、D其中任意一个都有可能被唤醒,如果C被唤醒,但C没有再去判断number的状态,那C将继续去执行,则number会继续增加,变为2,出现了不需要的结果。所以在判断语句中,不要使用if(),而是使用while()语句来判断number的状态,这样就可以避免异常状态的出现。

void notify()

Wakes up a single thread that is waiting on this object's monitor.
void notifyAll()

Wakes up all threads that are waiting on this object's monitor.

Java线程通信——wait() 和 notify()的更多相关文章

  1. 第23章 java线程通信——生产者/消费者模型案例

    第23章 java线程通信--生产者/消费者模型案例 1.案例: package com.rocco; /** * 生产者消费者问题,涉及到几个类 * 第一,这个问题本身就是一个类,即主类 * 第二, ...

  2. Java线程通信

    Java线程通信 螣蛇乘雾,终为土灰. 多个线程协同工作完成某个任务时就会涉及到线程间通信问题.如何使各个线程之间同时执行,顺序执行.交叉执行等. 一.线程同时执行 创建两个线程a和b,两个线程内调用 ...

  3. 多线程一共就俩问题:1.线程安全(访问共享数据) 2.线程通信(wait(),notify())

    多线程一共就俩问题:1.线程安全(访问共享数据) 2.线程通信(wait(),notify()) 1.线程安全,无非就是加锁,访问共享资源时,synchronized 2.线程通信,就是控制各个线程之 ...

  4. Java 线程通信

    线程通信用来保证线程协调运行,一般在做线程同步的时候才需要考虑线程通信的问题. 1.传统的线程通信 通常利用Objeclt类提供的三个方法: wait() 导致当前线程等待,并释放该同步监视器的锁定, ...

  5. java线程通信与协作小结 多线程中篇(十六)

      在锁与监视器中我们对Object中的方法进行了简单介绍 以监视器原理为核心,三个方法:wait,notify.notifyAll,可以完成线程之间的通信 当然,不会像“语言”似的,有多种多样的沟通 ...

  6. Java线程通信-生产者消费者问题

    线程通信示例——生产者消费者问题 这类问题描述了一种情况,假设仓库中只能存放一件产品,生产者将生产出来的产品放入仓库,消费者将仓库中的产品取走消费.假设仓库中没有产品,则生产者可以将 产品放入仓库,有 ...

  7. 9.线程通信wait、notify

    线程之间通信 1.线程是操作系统的独立的个体,但这些个体如果不经过特殊处理就不能成为一个整体. 2.使用wait.notify,方法实现线程通信(2个方法都是需要object方法) 3.wait(释放 ...

  8. java——线程的wait()和notify()

    这是一个关于生产者和消费者的线程通信的例子: package thread_test; public class PCThread { public static void main(String[] ...

  9. JAVA线程通信之生产者与消费者

    package cn.test.hf.test3; import java.util.concurrent.locks.Condition;import java.util.concurrent.lo ...

随机推荐

  1. 51nod 平均数(二分+树状数组)

    题目链接: 平均数 基准时间限制:4 秒 空间限制:131072 KB 分值: 80 LYK有一个长度为n的序列a. 他最近在研究平均数. 他甚至想知道所有区间的平均数,但是区间数目实在太多了. 为了 ...

  2. freeCodeCamp:Where art thou

    写一个 function,它遍历一个对象数组(第一个参数)并返回一个包含相匹配的属性-值对(第二个参数)的所有对象的数组.如果返回的数组中包含 source 对象的属性-值对,那么此对象的每一个属性- ...

  3. 各种LICENSE的作用--GET

    许 多开发者和设计者希望把他们的作品作为开源项目共享,他们希望其他人能够利用和共享他们的代码. 而各种开源社区就是因为这个原因而充满活力.开源软件可以用于你能想象得到的任何应用程序,许多web设计人员 ...

  4. Hadoop YARN配置参数剖析—RM与NM相关参数

    注意,配置这些参数前,应充分理解这几个参数的含义,以防止误配给集群带来的隐患.另外,这些参数均需要在yarn-site.xml中配置. 1.    ResourceManager相关配置参数 (1) ...

  5. IOS中调整UI控件位置和尺寸

    1.frame(修改位置和尺寸):以父控件左上角为坐标原点,在其父控件中的位置和尺寸. //frame属性中的坐标点不能直接修改 CGRect tempFrame = self.v.frame; // ...

  6. shell常用代码积累

    1.使用getopts从命令行接收参数 例: while getopts h:u:p: OPTION do case $OPTION in h) echo "主机地址:$OPTARG&quo ...

  7. Js判断CSS文件加载完毕的实例教程

    要判断这个 CSS 文件是否加载完毕,各个浏览器的做法差异比较大,这次要说IE浏览器做的不错,我们可以直接通过onload方法来处理CSS加载完成以后的处理: 代码如下 复制代码 // 代码节选至se ...

  8. iOS数据持久化(三)

    #pragma mark - Core Data stack /** * @synthesize 关联成员变量和属性 */ @synthesize managedObjectContext = _ma ...

  9. UI2_QQ折叠-UITableViewController

    // CustomUITableViewController.h // UI2_QQ折叠-UITableViewController // // Created by zhangxueming on ...

  10. UI1_UIScrollView

    // // AppDelegate.m // UI1_UIScrollView // // Created by zhangxueming on 15/7/10. // Copyright (c) 2 ...