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 ...
随机推荐
- 怒刷DP之 HDU 1029
Ignatius and the Princess IV Time Limit:1000MS Memory Limit:32767KB 64bit IO Format:%I64d &a ...
- codeforces 678C C. Joty and Chocolate(水题)
题目链接: C. Joty and Chocolate time limit per test 1 second memory limit per test 256 megabytes input s ...
- Pascal 语言中字符与字符串
[题目]输入一段文章(255个字符以内),求文章中单词的个数,相同单词只记一次,The 和 the 视作相同. [敲代码] //网友代码 var article,w:string; arr:array ...
- PHP计算中英混输字符串长度
最近做项目中碰到需要post value length check的这么一个情况 有这么一个需求, 需要backend来处理post过来的中英混输的数据. 对其限制的规则是中文10个字符, 英文20个 ...
- 十大Intellij IDEA快捷键(转)(2015年06月15日)
注:本文转自:http://blog.csdn.net/dc_726/article/details/42784275 Intellij IDEA中有很多快捷键让人爱不释手,stackoverflow ...
- 九、Android学习笔记_ Android开发中使用软引用和弱引用防止内存溢出
在<Effective Java 2nd Edition>中,第6条“消除过期的对象引用”提到,虽然Java有 垃圾回收机制,但是只要是自己管理的内存,就应该警惕内存泄露的问题,例如的对象 ...
- sql Truncate 与 delete的区别
Truncate 语法 TRUNCATE TABLE [ { database_name .[ schema_name ] . | schema_name . } ] table_na ...
- php 检查email电子邮件函数(奇葩写法)
以前写的一个PHP表单电子邮件发送程序,其中采用如下方法来验证电子邮件地址格式是否正确: 代码如下 复制代码 eregi("^[_a-z0-9-]+(.[_a-z0-9-]+)*@[a-z0 ...
- Xcode6 模拟器不显示键盘
在学习加法计算器时,程序运行后发现点击模拟器上的输入框时有时候键盘可以弹出来,有时候又弹不出来. 网上查询结果只需要在模拟器的菜单中找到hardware -> keyboard -> 取消 ...
- 8套迷人精致的CSS3 3D按钮动画
1.纯CSS3 3D按钮 按钮酷似牛奶般剔透 CSS3按钮一般都可以设计的非常漂亮,利用投影.渐变等CSS3属性特效可以把按钮渲染的十分动感.今天分享的这款CSS3按钮外观非常特别,它看上去酷似晶莹剔 ...