多线程(四)wait()、notify()以及notifyAll()
六、线程的等待和唤醒
1.wait()和notify()的简单示范
public class Wait extends Thread{
public synchronized void run()
{
System.out.println(getName()+"执行notify()");
notify();
}
public static void main(String []args) {
Wait w = new Wait();
synchronized (w){
try {
w.start();
System.out.println(Thread.currentThread().getName() + "睡眠");
Thread.sleep(3000);
System.out.println(Thread.currentThread().getName() + "等待");
w.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
程序结果:
main睡眠
main等待
Thread-0执行notify()
首先注意:wait()和notify()必须在synchronized代码块中。
这程序的流程是main线程先睡眠,然后被暂停,之后w线程执行notify()方法唤醒main(),如此就引出以下几个问题:
sleep()和wait()究竟有什么区别?
线程睡眠(sleep)不会放弃当前锁,而等待(wait)会。正如上面程序所示,即使线程睡眠的3000毫秒,但并没有放弃w的对象锁,所以run()方法不能获取w的对象锁,因此没有执行,体现在没有打印调用方法。而wait()执行后,main线程放弃对象锁,w线程获得自己的对象锁执行notify()方法,唤醒线程main,main继续执行。
w.wait()为什么是main线程暂停?
我们都知道sleep()是Thread类的静态方法,因此会睡眠执行该代码的线程。值得注意的是wait()虽然是Object()的实例方法,但是也具有sleep()类似的性质,即使运行代码的线程进入等待态。
notify()和notifyAll()的区别?
大部分人都耳熟能详,notify()唤醒监听器上一个线程,notifyAll()唤醒所有线程。notify()方法会随机唤醒一个线程,因此设计程序必须要合理。
wait()和wait(long mil)?
wait()需要notify()或者notifyAll()方法唤醒,而wait(long mil)同样,但是如果超过指定的时间还没有唤醒,那么自动唤醒。
这个程序其实是模仿博主如果天空不死的一个思路,而存在一个争论,即本程序中notify()方法删除,程序也会接着执行,原因位置,博主给出的解释是w线程结束后,释放的锁会由剩下的线程争抢,而该程序只剩下main线程,因此不必唤醒。显然有一点勉强,希望有大佬能解释。
2.wait()方法和notify()方法为何设置在Object类中?
wait()方法其实核心与sleep()不同就是放弃线程持有的对象锁,而notify()方法唤醒线程时只能在获取该对象锁的情况才有效(即唤醒线程和等待线程必须是同一把对象锁才能唤醒)。既然两者是通过对象锁联系到一起,那对象就有可能是几乎任何类的实例,因此将wait()、notify()和notifuAll()方法放在Object类中是合适的
3.一个简单的程序
我们通过wait()和notify()实现一个简单的功能,题目大致如下:
现有助理录不断入学生成绩,没录入一个学生,分析出总成绩和平均成绩
public class Grade {
int g;
static double avg=0;
static int num=0;
boolean b=true;
public synchronized void input(int g)
{
if(!b) {
try {
// System.out.println("暂停"+Thread.currentThread().getName());
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.g = g;
System.out.println("写入成绩"+g);
b=!b;
notify();
}
public synchronized void analyze()
{
if(b) {
try {
// System.out.println("暂停"+Thread.currentThread().getName());
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
double sum=(avg*num+g);
num++;
avg = sum / num;
System.out.println("Average of Grade is "+Grade.avg+", sum is "+sum);
b=!b;
notify();
}
public static void main(String []args)
{
Grade gr=new Grade();
C_Input c1=new C_Input(gr);
C_Analyze c2=new C_Analyze(gr);
c1.start();
c2.start();
}
}
class C_Input extends Thread
{
Grade grade;
public C_Input (Grade g)
{
grade=g;
}
public void run()
{
for(int i=0;i<5;i++) {
int mg=(int)(Math.random()*100);
grade.input(mg);
}
}
}
class C_Analyze extends Thread
{
Grade grade;
public C_Analyze (Grade g)
{
grade=g;
}
public void run()
{
for(int i=0;i<5;i++) {
grade.analyze();
}
}
}
结果:
写入成绩60
Average of Grade is 60.0, sum is 60.0
写入成绩84
Average of Grade is 72.0, sum is 144.0
写入成绩22
Average of Grade is 55.333333333333336, sum is 166.0
写入成绩96
Average of Grade is 65.5, sum is 262.0
写入成绩59
Average of Grade is 64.2, sum is 321.0
线程就先讲到这里,因为主要还是打基础,后面进阶我还会重新回来的!
多线程(四)wait()、notify()以及notifyAll()的更多相关文章
- Java多线程中wait, notify and notifyAll的使用
本文为翻译文章,原文地址:http://www.journaldev.com/1037/java-thread-wait-notify-and-notifyall-example 在Java的Obje ...
- 并发和多线程(四)--wait、notify、notifyAll、sleep、join、yield使用详解
wait.notify.notifyAll 这三个方法都是属于Object的,Java中的类默认继承Object,所以在任何方法中都可以直接调用wait(),notifyAll(),notify(), ...
- 多线程协作wait、notify、notifyAll方法简介理解使用 多线程中篇(十四)
在锁与监视器中有对wait和notify以及notifyAll进行了简单介绍 所有对象都有一个与之关联的锁与监视器 wait和notify以及notifyAll之所以是Object的方法就是因为任何一 ...
- Java多线程 wait, notify 和 notifyAll
Java的Object类 public class Object { public final native void notify(); public final native void notif ...
- Java多线程---------同步与死锁:synchronized;等待与唤醒:wait、notify、notifyAll;生命周期
1.问题的引出 class MyThread implements Runnable{ private int ticket = 5 ; // 假设一共有5张票 public void run(){ ...
- Java多线程的wait(),notify(),notifyAll()
在多线程的情况下.因为多个线程与存储空间共享相同的过程,同时带来的便利.它也带来了访问冲突这个严重的问题. Java语言提供了一种特殊的机制来解决这类冲突,避免同一数据对象由多个线程在同一时间访问. ...
- Java多线程:wait(),notify(),notifyAll()
1. wait(),notify(),notifyAll() 2. wait() 2.1. wait() 2.2. wait(long timeout) 2.3. wait(long timeout, ...
- java锁与监视器概念 为什么wait、notify、notifyAll定义在Object中 多线程中篇(九)
在Java中,与线程通信相关的几个方法,是定义在Object中的,大家都知道Object是Java中所有类的超类 在Java中,所有的类都是Object,借助于一个统一的形式Object,显然在有些处 ...
- Java线程和多线程(二)——对象中的wait,notify以及notifyAll方法
Java对象中的wait,notify以及notifyAll方法 在Java的Object类中包含了3个final的方法,这三个方法允许线程来交流资源是否被锁定.这三个方法就是wait(),notif ...
随机推荐
- CF792E Colored Balls【思维】
题目传送门 考试的时候又想到了小凯的疑惑,真是中毒不浅... 设每一个数都可以被分成若干个$k$和$k+1$的和.数$x$能够被分成若干个$k$和$k+1$的和的充要条件是:$x%k<=floo ...
- C学习笔记-多源文件的编译
多源文件的意义 为了精简代码和更好的维护代码,往往需要将一些功能实现的代码与主函数代码分开来 在使用的时候再主函数中调用 多源文件的使用 假设现有my.c和main.c两个源代码文件,现在要再main ...
- C语言Ⅰ博客作业09
这个作业属于那个课程 C语言程序设计II 这个作业要求在哪里 https://edu.cnblogs.com/campus/zswxy/CST2019-3/homework/10029 我在这个课程的 ...
- 解决VScode无法输出中文的问题
VScode输出框输出不了中文 解决方法: 在环境变量里面增加:PYTHONIOENCODING为UTF-8 重启vscode即可
- 快速排序的Python代码实现
选择一个数,和它后面的数比较,把比它小的放在它的左边,大的在右边(位置可能会因为左边元素的添加而右移) def quick_sort(arr): if arr==[]: return[] else: ...
- 基于SpringBoot从零构建博客网站 - 整合ehcache和开发注册登录功能
对于程序中一些字典信息.配置信息应该在程序启动时加载到缓存中,用时先到缓存中取,如果没有命中,再到数据库中获取同时放到缓存中,这样做可以减轻数据库层的压力.目前暂时先整合ehcache缓存,同时预留了 ...
- 关于 resultType 与 parameterType 的基本使用的区别
以下关于 resultType 与 parameterType 的基本使用的区别 : 1.使用 resultType : 主要针对于从数据库中提取相应的数据出来 2.使 ...
- Java 面向对象的设计原则
一. 1.面向对象思想的核心: 封装.继承.多态. 2.面向对象编程的追求: 高内聚低耦合的解决方案: 代码的模块化设计: 3.什么是设计模式: 针对反复出现的问题的经典解决方案,是对特定条件下( ...
- Python(六) —— 网络请求
接口调用 接口调用有几个模块可以用:urllib 和 requests ,urllib 是内置的模块,极其不好用,强烈推荐用 requests 模块 get 请求 1.普通的 get 请求 impor ...
- 【原创】大叔经验分享(57)hue启动coordinator时报错
hue启动coordinator时报错,页面返回undefinied错误框: 后台日志报错: runcpserver.log [13/May/2019 04:34:55 -0700] middlewa ...