Object类中的两个方法——wait和notify使用总结
Object类中的wait 、和 notify方法是用来处理线程的方法,既然定义在Object类中,两个方法的重要程度可见一斑:
两个方法的使用上都很复杂:通过阅读API获得更多对方法的理解:
The current thread must own this object'smonitor. The thread releases ownership of this monitor and waits until anotherthread notifies threads waiting on this object's monitor to wake up eitherthrough a call to thenotify
method or the notifyAll
method. The thread then waits until it can re-obtain ownership ofthe monitor and resumes execution
“当前的线程必须要获得对象的锁!”
实现这个条件的做法就是wait 方法一定要定义在synchronized方法中或者synchronized代码块中;
线程必须要两次获得锁才能完全的执行synchronized中的所有内容;
当第一次调用到达wait方法时,The thread realeases ownership of this monitor and waituntil another thread notifies threads waiting on this …
线程会暂时释放锁的拥有权,等待其他线程的notify方法或者notifyAll方法唤醒该线程,继续执行代码!
30.
下面一个程序要求定义两个线程类,一个实现将目标加一,一个实现将目标减一,目标初始值为零,要求加一减一交替进行;
显然的单纯调用synchronized是无法满足条件的,需要使用wait,和notify方法;
package thread;
publicclass ThreadTest
{
publicstaticvoid main(String[] args)
{
ThreadDemo2 demo = new ThreadDemo2();
ThreadIncrease test1 = new ThreadIncrease(demo);
ThreadDecrease test2 = new ThreadDecrease(demo);
test1.start();
test2.start();
}
}
class ThreadDemo2
{
privateintnum = 0;
publicsynchronizedvoid Increase()
{
/*
* 下面的代码是核心代码
* 什么时候要让线程等待,当然是不符合条件的时候
* 目的是想让num = 0 的时候才执行加一的操作,当num不等于零的时候会执行wait等待通知
* 当通知num已经变为0时,wait结束,执行下面语句num++;
* 然后执行notify方法!
* 当然的一说Java中的synchronized总是伴随着wait和notify方法共同的存在;
*/
if(num != 0)
{
try
{
wait();
}
catch (InterruptedException e)
{
// TODO Auto-generatedcatch block
e.printStackTrace();
}
}
num ++;
System.out.println(num);
notify();
}
publicsynchronizedvoid decrease()
{
if(num == 0)
{
try
{
wait();
}
catch (InterruptedException e)
{
// TODO Auto-generatedcatch block
e.printStackTrace();
}
}
num --;
System.out.println(num);
notify();
}
}
class ThreadIncreaseextends Thread
{
private ThreadDemo2demo;
public ThreadIncrease(ThreadDemo2 demo)
{
this.demo = demo;
}
@Override
publicvoid run()
{
for(int i = 0 ; i < 15; i ++)
{
demo.Increase();
}
}
}
class ThreadDecreaseextends Thread
{
private ThreadDemo2demo;
public ThreadDecrease(ThreadDemo2 demo)
{
this.demo = demo;
}
@Override
publicvoid run()
{
for(int i = 0 ; i < 15; i ++)
{
demo.decrease();
}
}
}
31.
可惜的是上面的代码仍然有着致命的弱点,线程并不仅仅有两个,而且是两个相对的线程!
致命的弱点在于: 当线程在wait的时候它并不知道其他的线程到底做了什么!
现在我们将增加一个Increase线程类,和一个Decrease线程类
,并且调用它们的start方法运行后,你将看到这样的结果:
我们足以看到代码的脆弱性,为什么会出现这种情况,更糟糕的是结果是随机的!上面已经说得很清楚了:当线程在wait的时候,它不知道其他的线程正在做什么,
所以需要将代码变得更加健壮:
我们举一个为什么会出现这种情况的原因之一:
我们假设线程1、2调用增加方法,线程3、4调用减少方法
假设线程3 先访问了减少方法,因为此时num的值为0,所以wait,并且交出ownership,假设线程4又访问了减少方法,同样的wait,并且交出所有权,再假设线程1访问了增加方法,将num的值变为1,并且调用notify方法,假设notify了线程3,线程3将num的值变为0;并且notify,如果此时notify了线程4,那么悲剧就会发生了,线程4醒来后,会继续将num减一,变为-1,一步错,后面就全错了;
缺点就在于notify的随机性,所以在某个wait方法被唤醒时,增加判断条件,如果不符合条件,继续wait,显然 while循环是最合适的
!
全部的变化只需要将 if 改为 while!!
由于num是成员变量被线程共享,每当wait被唤醒,都会判断一次;
package thread;
publicclass ThreadTest
{
publicstaticvoid main(String[] args)
{
ThreadDemo2 demo = new ThreadDemo2();
ThreadIncrease test1 = new ThreadIncrease(demo);
ThreadDecrease test2 = new ThreadDecrease(demo);
ThreadIncrease test3 = new ThreadIncrease(demo);
ThreadDecrease test4 = new ThreadDecrease(demo);
test1.start();
test2.start();
test3.start();
test4.start();
}
}
class ThreadDemo2
{
privateintnum = 0;
publicsynchronizedvoid Increase()
{
/*
* 下面的代码是核心代码
* 什么时候要让线程等待,当然是不符合条件的时候
* 目的是想让num = 0 的时候才执行加一的操作,当num不等于零的时候会执行wait等待通知
* 当通知num已经变为0时,wait结束,执行下面语句num++;
* 然后执行notify方法!
* 当然的一说Java中的synchronized总是伴随着wait和notify方法共同的存在;
*/
while(num != 0)
{
try
{
wait();
}
catch (InterruptedException e)
{
// TODO Auto-generatedcatch block
e.printStackTrace();
}
}
num ++;
System.out.println(num);
notify();
}
publicsynchronizedvoid decrease()
{
while(num == 0)
{
try
{
wait();
}
catch (InterruptedException e)
{
// TODO Auto-generatedcatch block
e.printStackTrace();
}
}
num --;
System.out.println(num);
notify();
}
}
class ThreadIncreaseextends Thread
{
private ThreadDemo2demo;
public ThreadIncrease(ThreadDemo2 demo)
{
this.demo = demo;
}
@Override
publicvoid run()
{
for(int i = 0 ; i < 15; i ++)
{
try
{
Thread.sleep((long)(Math.random()*1000));
}
catch (InterruptedException e)
{
// TODO Auto-generatedcatch block
e.printStackTrace();
}
demo.Increase();
}
}
}
class ThreadDecreaseextends Thread
{
private ThreadDemo2demo;
public ThreadDecrease(ThreadDemo2 demo)
{
this.demo = demo;
}
@Override
publicvoid run()
{
for(int i = 0 ; i < 15; i ++)
{
try
{
Thread.sleep((long)(Math.random()*1000));
}
catch (InterruptedException e)
{
// TODO Auto-generatedcatch block
e.printStackTrace();
}
demo.decrease();
}
}
}
Object类中的两个方法——wait和notify使用总结相关推荐
- 创建一个 Rectangle类,添加width和lenght两个成员变量 在 Rectangle类中添加两种方法分别计算矩形的周长和面积 编程利用Rectangle输出一个矩形的周长和面积
创建一个 Rectangle类,添加width和lenght两个成员变量 在 Rectangle类中添加两种方法分别计算矩形的周长和面积 编程利用Rectangle输出一个矩形的周长和面积 publi ...
- 90页第三题,创建一个 Rectangle类,添加width和lenght两个成员变量 在 Rectangle类中添加两种方法分别计算矩形的周长和面积 ,编程利用Rectangle输出一个矩形的
//90页第三题,创建一个 Rectangle类,添加width和lenght两个成员变量 //在 Rectangle类中添加两种方法分别计算矩形的周长和面积 //编程利用Rectangle输出一个矩 ...
- Object类中的五种方法
clone() Object类源码:protected native Object clone() throws CloneNotSupportedException; 这里有个问题:为什么Sun公司 ...
- Object类中hashCode()和equals()方法详解(附图)
下图是规范中要求的: 图解:比如equals相等的箭头指向hashcode相等,标示equals相等那么必有hashcode相等.另外有两个箭头指向别人的标示可能是其中之一. //JAVA代码: pu ...
- java object类的方法,JAVA中Object类中 有几个方法?
慕标5265247 1.所有方法:1. getClass()2. hashCode()3. equals()4. toString()5. clone()6. wait()...7. notify() ...
- java Object类中的各个方法及其作用
原文链接 一.简介Object类 Object类是所有类的父类,即每个类都直接或简介继承自该类.所以一个Object类型的变量可以引用任何对象,不论是类实例还是数组. 在不明确给出父类的情况下,Jav ...
- 设计一个接口, 并设计一个实现类实现该接口,演示它们的使用。具体,创建一个名称为Person的接口,在接口中定义两个方法sayHello()和sayBye()。
设计一个接口, 并设计一个实现类实现该接口,演示它们的使用. 具体,创建一个名称为Person的接口,在接口中定义两个方法sayHello()和sayBye().然后,创建两个实现了Person接口的 ...
- python中的object是什么意思_Python object类中的特殊方法代码讲解
python版本:3.8class object: """ The most base type """ # del obj.xxx或del ...
- object类中的equals与自定义equals方法详解
object类中的equals与自定义equal方法详解 1.this怎么理解?this == obj表示什么? this就是当前你new出来的对象,这里指谁调用equal方法this指的就是谁,ob ...
最新文章
- 扎克伯格All in元宇宙,公司更名Meta,「脸」不要了
- Java学习之Hello World 第一个小程序
- HDU 2087剪花布条 KMP
- Codeforces Round #394 (Div. 2) A. Dasha and Stairs 水题
- 安卓总线传输协议常用关键词
- 计算机里的文件丢失6,丢失的文件怎么恢复?腾讯电脑管家恢复电脑丢失文件的方法介绍...
- 如何制作一个横版格斗过关游戏 2 Cocos2d x 2 0 4
- 计算机二级-JAVA基础知识1
- php有哪些程序结构,PHP常用控制结构
- Spring 配置文件加载原理
- 三台虚拟机如何通过GNS3互通
- 想做程序员?不同方向入门路线全解
- cnpack代码输入助手失效的解决办法
- 中文转换成拼音实施方法
- 服务器开机风扇转但无显示,电脑开机主机风扇在转,显示器却显示无信号是怎么回事?...
- 利用Python写个新年贺卡生成器,提前祝大家小伙伴们新年快乐呀~
- 【UVM基础】UVM 树形组织结构
- 【JVM】运行时数据区介绍,程序计数器和虚拟机栈详解
- 【源码阅读】GAT:GRAPH ATTENTION NETWORKS
- Java接入支付宝支付(沙箱)