Java线程通信——wait() 和 notify()
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,当设定的睡眠时间超时后,线程会马上继续执行。
一个线程变为一个对象的锁的拥有者,可以通过三种途径:
- 运行这个对象的synchronized的实例方法。
- 运行这个对象的synchronized的语句块。
- 对于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()的更多相关文章
- 第23章 java线程通信——生产者/消费者模型案例
第23章 java线程通信--生产者/消费者模型案例 1.案例: package com.rocco; /** * 生产者消费者问题,涉及到几个类 * 第一,这个问题本身就是一个类,即主类 * 第二, ...
- Java线程通信
Java线程通信 螣蛇乘雾,终为土灰. 多个线程协同工作完成某个任务时就会涉及到线程间通信问题.如何使各个线程之间同时执行,顺序执行.交叉执行等. 一.线程同时执行 创建两个线程a和b,两个线程内调用 ...
- 多线程一共就俩问题:1.线程安全(访问共享数据) 2.线程通信(wait(),notify())
多线程一共就俩问题:1.线程安全(访问共享数据) 2.线程通信(wait(),notify()) 1.线程安全,无非就是加锁,访问共享资源时,synchronized 2.线程通信,就是控制各个线程之 ...
- Java 线程通信
线程通信用来保证线程协调运行,一般在做线程同步的时候才需要考虑线程通信的问题. 1.传统的线程通信 通常利用Objeclt类提供的三个方法: wait() 导致当前线程等待,并释放该同步监视器的锁定, ...
- java线程通信与协作小结 多线程中篇(十六)
在锁与监视器中我们对Object中的方法进行了简单介绍 以监视器原理为核心,三个方法:wait,notify.notifyAll,可以完成线程之间的通信 当然,不会像“语言”似的,有多种多样的沟通 ...
- Java线程通信-生产者消费者问题
线程通信示例——生产者消费者问题 这类问题描述了一种情况,假设仓库中只能存放一件产品,生产者将生产出来的产品放入仓库,消费者将仓库中的产品取走消费.假设仓库中没有产品,则生产者可以将 产品放入仓库,有 ...
- 9.线程通信wait、notify
线程之间通信 1.线程是操作系统的独立的个体,但这些个体如果不经过特殊处理就不能成为一个整体. 2.使用wait.notify,方法实现线程通信(2个方法都是需要object方法) 3.wait(释放 ...
- java——线程的wait()和notify()
这是一个关于生产者和消费者的线程通信的例子: package thread_test; public class PCThread { public static void main(String[] ...
- JAVA线程通信之生产者与消费者
package cn.test.hf.test3; import java.util.concurrent.locks.Condition;import java.util.concurrent.lo ...
随机推荐
- hdu 2473 并查集
思路:每次合并时,都是给一个虚拟的根. #include<map> #include<Set> #include<cmath> #include<queue& ...
- hdu1331 按着题目的公式直接写
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #d ...
- CF 322E - Ciel the Commander 树的点分治
树链剖分可以看成是树的边分治,什么是点分治呢? CF322E - Ciel the Commander 题目:给出一棵树,对于每个节点有一个等级(A-Z,A最高),如果两个不同的节点有相同等级的父节点 ...
- MVC3 Razor视图引擎的基础语法
好久没有关注微软的开发了,今天看到了MVC3,顺便学习学习,我觉得Razor是个不错的做法,比使用<%%>简单多了,而且好看.首先“_”开头的cshtml文档将不能在服务器上访问,和asp ...
- Ubuntu 16.04 - python3 安装mysql驱动
阿西吧,今天碰到一件特别蛋疼的事,给Ubuntu安装Python的MySQL驱动,驱动显示安装成功了 pip install mysql-connector 但是 在程序中导入,老是报错. Trace ...
- C#去掉周六周日的算法
/// <summary> /// 用来获取工作日(不含周六周日) /// </summary> /// <param name="dtSub"> ...
- JSP之错误信息提示
MessageResource.properties配置文件: RegisterAction注册: package com.caiduping.action; import javax.servlet ...
- Markdown 学习资源
语法 Mastering Markdown Markdown Cheatsheet pandoc 在线预览工具
- 单一职责原则(SRP)
一个类应仅有一个引起它变化的原因. 内聚性. 每个Responsibility都是变化的一个轴线.当需求变化时,该变化会反映为类的职责的变化 当一个类耦合了多个职责时,一个职责的变化会消弱或抑制其他职 ...
- 10款基于jquery实现的超酷动画源码
1.jQuery二级下拉菜单 下拉箭头翻转动画 之前我们分享过不少基于jQuery的二级下拉菜单,甚至是多级的下拉菜单,比如这款jQuery/CSS3飘带状多级下拉菜单就非常华丽.但今天要介绍的这款j ...