1. wait(), notify(), notifyAll()等方法介绍

在Object.java中,定义了wait(), notify()和notifyAll()等接口。wait()的作用是让当前线程进入等待状态,同时,wait()也会让当前线程释放它所持有的锁。而notify()和notifyAll()的作用,则是唤醒当前对象上的等待线程;notify()是唤醒单个线程,而notifyAll()是唤醒所有的线程。

Object类中关于等待/唤醒的API详细信息如下:

notify()-- 唤醒在此对象监视器上等待的单个线程。

notifyAll()  -- 唤醒在此对象监视器上等待的所有线程。

wait()                               -- 让当前线程处于“等待(阻塞)状态”,“直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法”,当前线程被唤醒(进入“就绪状态”)。

wait(long timeout)                -- 让当前线程处于“等待(阻塞)状态”,“直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者超过指定的时间量”,当前线程被唤醒(进入“就绪状态”)。

wait(long timeout, int nanos)-- 让当前线程处于“等待(阻塞)状态”,“直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者其他某个线程中断当前线程,或者已超过某个实际时间量”,当前线程被唤醒(进入“就绪状态”)。

2. 为什么notify(), wait()等函数定义在Object中,而不是Thread中

Object中的wait(), notify()等函数,和synchronized一样,会对“对象的同步锁”进行操作。

wait()会使“当前线程”等待,因为线程进入等待状态,所以线程应该释放它锁持有的“同步锁”,否则其它线程获取不到该“同步锁”而无法运行!

OK,线程调用wait()之后,会释放它锁持有的“同步锁”;而且,根据前面的介绍,我们知道:等待线程可以被notify()或notifyAll()唤醒。现在,请思考一个问题:notify()是依据什么唤醒等待线程的?或者说,wait()等待线程和notify()之间是通过什么关联起来的?答案是:依据“对象的同步锁”。

负责唤醒等待线程的那个线程(我们称为“唤醒线程”),它只有在获取“该对象的同步锁”(这里的同步锁必须和等待线程的同步锁是同一个),并且调用notify()或notifyAll()方法之后,才能唤醒等待线程。虽然,等待线程被唤醒;但是,它不能立刻执行,因为唤醒线程还持有“该对象的同步锁”。必须等到唤醒线程释放了“对象的同步锁”之后,等待线程才能获取到“对象的同步锁”进而继续运行。

总之,notify(), wait()依赖于“同步锁”,而“同步锁”是对象锁持有,并且每个对象有且仅有一个!这就是为什么notify(), wait()等函数定义在Object类,而不是Thread类中的原因。

3. yield()介绍

yield()的作用是让步。它能让当前线程由“运行状态”进入到“就绪状态”,从而让其它具有相同优先级的等待线程获取执行权;但是,并不能保证在当前线程调用yield()之后,其它具有相同优先级的线程就一定能获得执行权;也有可能是当前线程又进入到“运行状态”继续运行!

4. yield() 与 wait()的比较

我们知道,wait()的作用是让当前线程由“运行状态”进入“等待(阻塞)状态”的同时,也会释放同步锁。而yield()的作用是让步,它也会让当前线程离开“运行状态”。它们的区别是:

(01) wait()是让线程由“运行状态”进入到“等待(阻塞)状态”,而不yield()是让线程由“运行状态”进入到“就绪状态”。

(02) wait()是会线程释放它所持有对象的同步锁,而yield()方法不会释放锁。

// YieldLockTest.java 的源码

public class YieldLockTest{

private static Object obj = new Object();

public static void main(String[] args){

ThreadA t1 = new ThreadA("t1");

ThreadA t2 = new ThreadA("t2");

t1.start();

t2.start();

}

static class ThreadA extends Thread{

public ThreadA(String name){

super(name);

}

public void run(){

// 获取obj对象的同步锁

synchronized (obj) {

for(int i=0; i <10; i++){

System.out.printf("%s [%d]:%d\n", this.getName(), this.getPriority(), i);

// i整除4时,调用yield

if (i%4 == 0)

Thread.yield();

}

}

}

}

}

(某一次)运行结果:

t1 [5]:0

t1 [5]:1

t1 [5]:2

t1 [5]:3

t1 [5]:4

t1 [5]:5

t1 [5]:6

t1 [5]:7

t1 [5]:8

t1 [5]:9

t2 [5]:0

t2 [5]:1

t2 [5]:2

t2 [5]:3

t2 [5]:4

t2 [5]:5

t2 [5]:6

t2 [5]:7

t2 [5]:8

t2 [5]:9

结果说明:

主线程main中启动了两个线程t1和t2。t1和t2在run()会引用同一个对象的同步锁,即synchronized(obj)。在t1运行过程中,虽然它会调用Thread.yield();但是,t2是不会获取cpu执行权的。因为,t1并没有释放“obj所持有的同步锁”!

5. sleep()介绍

sleep() 定义在Thread.java中。

sleep() 的作用是让当前线程休眠,即当前线程会从“运行状态”进入到“休眠(阻塞)状态”。sleep()会指定休眠时间,线程休眠的时间会大于/等于该休眠时间;在线程重新被唤醒时,它会由“阻塞状态”变成“就绪状态”,从而等待cpu的调度执行。

6. sleep() 与 wait()的比较

我们知道,wait()的作用是让当前线程由“运行状态”进入“等待(阻塞)状态”的同时,也会释放同步锁。而sleep()的作用是也是让当前线程由“运行状态”进入到“休眠(阻塞)状态”。

但是,wait()会释放对象的同步锁,而sleep()则不会释放锁。

下面通过示例演示sleep()是不会释放锁的。

// SleepLockTest.java的源码

public class SleepLockTest{

private static Object obj = new Object();

public static void main(String[] args){

ThreadA t1 = new ThreadA("t1");

ThreadA t2 = new ThreadA("t2");

t1.start();

t2.start();

}

static class ThreadA extends Thread{

public ThreadA(String name){

super(name);

}

public void run(){

// 获取obj对象的同步锁

synchronized (obj) {

try {

for(int i=0; i <10; i++){

System.out.printf("%s: %d\n", this.getName(), i);

// i能被4整除时,休眠100毫秒

if (i%4 == 0)

Thread.sleep(100);

}

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}

}

主线程main中启动了两个线程t1和t2。t1和t2在run()会引用同一个对象的同步锁,即synchronized(obj)。在t1运行过程中,虽然它会调用Thread.sleep(100);但是,t2是不会获取cpu执行权的。因为,t1并没有释放“obj所持有的同步锁”!

注意,若我们注释掉synchronized (obj)后再次执行该程序,t1和t2是可以相互切换的。

java多线程notifyall_Java多线程:线程状态以及wait(), notify(), notifyAll()相关推荐

  1. 统计Java进程中的线程状态(jstack+linux)

    统计Java进程中的线程状态 第一步:查看Java进程ID 第二步:使用jstack命令dump线程信息,看看pid=45890进程中的线程都是什么状态 /usr/local/java/jdk1.8. ...

  2. java wait notifyall_Java多线程中的wait与notify,notifyall例子

    文章来给各位介绍一下Java多线程中的wait与notify,notifyall例子,希望文章能给各位朋友带来帮助哦. 在Java多线程编程中,wait()的作用的是让当前线程进入阻塞状态,notif ...

  3. java 多线程 notifyall_java多线程之 wait(),notify(),notifyAll()

    这几天在写一个java多线程服务器的功能,用到这些基础,自叹基础知识还需巩固,先写上一下这些说明,供自己和大家参考 wait(),notify(),notifyAll()不属于Thread类,而是属于 ...

  4. Java并发编程之线程状态总结

    线程状态 新创建(NEW):新创建了一个线程对象,但还没有调用start()方法,如new Thread(r). 可运行(RUNNABLE):调用start方法,线程处于runnable状态. 阻塞( ...

  5. java并发编程(十)使用wait/notify/notifyAll实现线程间通信

    转载请注明出处:http://blog.csdn.net/ns_code/article/details/17225469 wait()方法:public final void wait()  thr ...

  6. 清心阁--多线程系列之线程状态和主要转换方法(四)

    今天是圣诞节,在这里祝各位同学圣诞快乐Merry Christmas!

  7. java线程同步(synchronized,wait,notify,notifyAll)

    synchronized: 包括synchronized方法和synchronized块. synchronized方法使用this作为默认的"同步监视器",而synchroniz ...

  8. 【Java多线程】了解线程的锁池和等待池概念

    文章目录 一.内置锁 二.线程状态 线程的5种状态 线程状态图 线程释放锁的情况 线程阻塞和线程等待的区别 sleep.join.yield.wait区别 yield不释放锁案例 sleep不释放锁案 ...

  9. java 线程状态_【19期】为什么Java线程没有Running状态?

    Java虚拟机层面所暴露给我们的状态,与操作系统底层的线程状态是两个不同层面的事.具体而言,这里说的 Java 线程状态均来自于 Thread 类下的 State 这一内部枚举类中所定义的状态: 什么 ...

最新文章

  1. Nginx中Gzip压缩功能的实例配置
  2. rtsp摘要认证协议(Response计算方法)
  3. 重磅!Python又第一了!网友:为什么找不到好工作?真相让人脸红…
  4. 揭秘Android开发效率提升多倍的利器;Gradle
  5. python编写年金终值函数_看零件图的标题栏可了解()
  6. 用户组培训资料和资源
  7. springBoot中shiro与Redis整合的配置文件
  8. [Ubuntu Error]鼠标指针闪烁的解决方法
  9. python源码中的学习笔记_第9章_类与对象
  10. struts标签的使用
  11. 【Y9000x】单硬盘UEFI+GPT基于Win10安装Ubuntu18.04
  12. 信息论与编码_中大网络信息理论与编码研讨会成功举办 SYSU Workshop on Net. Info. Theory and Coding...
  13. 数据库添加字段的sql语句
  14. 神州行省内流量套餐6元500M申请,发送BLSN6到10086即可
  15. HP笔记本电源开关灯常亮,不能开机的处理
  16. viso画图时如何让右侧显示设置形状格式栏
  17. 三子棋小游戏(超详细)
  18. 星星之火-55:什么是微观量子?什么是量子的六大特征?什么是微观量子通信?
  19. 【mysql优化实战】第一章 建表
  20. 如何一下清空微信好友_怎么一次性删除微信朋友圈说说

热门文章

  1. [转]仿163网盘无刷新文件上传系统
  2. python中用于获取当前目录的是_python中获得当前目录和上级目录的实现方法
  3. C语言程序练习-L1-018 大笨钟 (10分)
  4. 中英文切换_王者荣耀:模拟战奖励一览,新增中英文切换,李白第二套星元来袭...
  5. Java黑皮书课后题第4章:*4.11(十进制转十六进制)编写程序,提示用户输入0~15之间的一个整数,显示其对应的十六进制数。对于不正确的输入数字,提示非法输入
  6. AGC034 F - RNG and XOR
  7. Groovy 设计模式 -- 借贷
  8. vue的递归组件以及三级菜单的制作
  9. Linux┊详解udev
  10. mac下在eclipse中怎样清除/切换svn