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使用总结相关推荐

  1. 创建一个 Rectangle类,添加width和lenght两个成员变量 在 Rectangle类中添加两种方法分别计算矩形的周长和面积 编程利用Rectangle输出一个矩形的周长和面积

    创建一个 Rectangle类,添加width和lenght两个成员变量 在 Rectangle类中添加两种方法分别计算矩形的周长和面积 编程利用Rectangle输出一个矩形的周长和面积 publi ...

  2. 90页第三题,创建一个 Rectangle类,添加width和lenght两个成员变量 在 Rectangle类中添加两种方法分别计算矩形的周长和面积 ,编程利用Rectangle输出一个矩形的

    //90页第三题,创建一个 Rectangle类,添加width和lenght两个成员变量 //在 Rectangle类中添加两种方法分别计算矩形的周长和面积 //编程利用Rectangle输出一个矩 ...

  3. Object类中的五种方法

    clone() Object类源码:protected native Object clone() throws CloneNotSupportedException; 这里有个问题:为什么Sun公司 ...

  4. Object类中hashCode()和equals()方法详解(附图)

    下图是规范中要求的: 图解:比如equals相等的箭头指向hashcode相等,标示equals相等那么必有hashcode相等.另外有两个箭头指向别人的标示可能是其中之一. //JAVA代码: pu ...

  5. java object类的方法,JAVA中Object类中 有几个方法?

    慕标5265247 1.所有方法:1. getClass()2. hashCode()3. equals()4. toString()5. clone()6. wait()...7. notify() ...

  6. java Object类中的各个方法及其作用

    原文链接 一.简介Object类 Object类是所有类的父类,即每个类都直接或简介继承自该类.所以一个Object类型的变量可以引用任何对象,不论是类实例还是数组. 在不明确给出父类的情况下,Jav ...

  7. 设计一个接口, 并设计一个实现类实现该接口,演示它们的使用。具体,创建一个名称为Person的接口,在接口中定义两个方法sayHello()和sayBye()。

    设计一个接口, 并设计一个实现类实现该接口,演示它们的使用. 具体,创建一个名称为Person的接口,在接口中定义两个方法sayHello()和sayBye().然后,创建两个实现了Person接口的 ...

  8. python中的object是什么意思_Python object类中的特殊方法代码讲解

    python版本:3.8class object: """ The most base type """ # del obj.xxx或del ...

  9. object类中的equals与自定义equals方法详解

    object类中的equals与自定义equal方法详解 1.this怎么理解?this == obj表示什么? this就是当前你new出来的对象,这里指谁调用equal方法this指的就是谁,ob ...

最新文章

  1. 扎克伯格All in元宇宙,公司更名Meta,「脸」不要了
  2. Java学习之Hello World 第一个小程序
  3. HDU 2087剪花布条 KMP
  4. Codeforces Round #394 (Div. 2) A. Dasha and Stairs 水题
  5. 安卓总线传输协议常用关键词
  6. 计算机里的文件丢失6,丢失的文件怎么恢复?腾讯电脑管家恢复电脑丢失文件的方法介绍...
  7. 如何制作一个横版格斗过关游戏 2 Cocos2d x 2 0 4
  8. 计算机二级-JAVA基础知识1
  9. php有哪些程序结构,PHP常用控制结构
  10. Spring 配置文件加载原理
  11. 三台虚拟机如何通过GNS3互通
  12. 想做程序员?不同方向入门路线全解
  13. cnpack代码输入助手失效的解决办法
  14. 中文转换成拼音实施方法
  15. 服务器开机风扇转但无显示,电脑开机主机风扇在转,显示器却显示无信号是怎么回事?...
  16. 利用Python写个新年贺卡生成器,提前祝大家小伙伴们新年快乐呀~
  17. 【UVM基础】UVM 树形组织结构
  18. 【JVM】运行时数据区介绍,程序计数器和虚拟机栈详解
  19. 【源码阅读】GAT:GRAPH ATTENTION NETWORKS
  20. Java接入支付宝支付(沙箱)

热门文章

  1. Tomcat虚拟目录的配置
  2. 进程隐藏与进程保护(SSDT Hook 实现)(三)
  3. 给网游写一个挂吧(二) – 启动外挂上
  4. 【Boost】boost库asio详解7——boost::asio::buffer用法
  5. Shell case esac语句
  6. 局域网arpsniffer源码剖析
  7. 客户端网络库实现真的很简单吗?
  8. 白话科普系列——网站靠什么提升加载速度?
  9. 微服务架构下 CI/CD 如何落地
  10. Python 日志模块Loguru的使用