博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java等待-通知机制 synchronized和waity()的使用实践
阅读量:4292 次
发布时间:2019-05-27

本文共 1563 字,大约阅读时间需要 5 分钟。

介绍

等待-通知机制java在多线程开发当中对锁等待的一种完善。 当一个线程无法满足当前工作的条件的时候,可以让其进入对象等待池,并释放掉当前锁对象。当其他线程调用notifyAll() 或者notify()的时候就会唤醒线程,将线程放入** 锁等待池**。 可以进行争夺锁对象。

使用方法

  1. 可以调用wait()方法将线程放入等待池。
  2. wait()需要和synchronized 关键字一起使用。需要放在synchronized内部使用,哪果放在外部使用jvm会抛了一个运行时异常:InterruptedException
  3. wait()不能和static静态方法一起使用。 在这里插入图片描述
  4. 如果synchronized锁定的是this。 在使用的时候就是使用this.wait()、this.notifyALl()。如果synchronized(object) 锁定的是某object对象,就需要使用object.wait(),object.notifyall()。

实践

思路

一个完整的等待-通知:线程首先获取互斥锁,当线程要求的条件不满足时,释放互诉锁,进入等待状态; 当要求的条件满足时,通知等待的线程,重新获取互斥锁。

经典写法:

while(条件不满足) {    wait();  }

实现

class Allocator {  private List als;  // 一次性申请所有资源  synchronized void apply(    Object from, Object to){    // 经典写法    while(als.contains(from) ||         als.contains(to)){      try{        wait();      }catch(Exception e){      }       }     als.add(from);    als.add(to);    }  // 归还资源  synchronized void free(    Object from, Object to){    als.remove(from);    als.remove(to);    notifyAll();  }}

尽量使用notifyALl()

notify()是会随机地通知等待队列中的一个线程,notifyAll()会通知等待队列中的所有线程。

notify()在使用的时候只会随机选择一个线程进入锁等待池,而如果被唤醒的线程需要的锁对象仍然在使用,那这个线程就无法被执行。可真正可以获取锁对象的线程则无法被唤醒执行。

sleep()和wait()的区别

wait()方法与sleep()方法的不同之处在于,wait()方法会释放对象的“锁标志”。当调用某一对象的wait()方法后,会使当前线程暂停执行,并将当前线程放入对象等待池中,直到调用了notify()方法后,将从对象等待池中移出任意一个线程并放入锁标志等待池中,只有锁标志等待池中的线程可以获取锁标志,它们随时准备争夺锁的拥有权。当调用了某个对象的notifyAll()方法,会将对象等待池中的所有线程都移动到该对象的锁标志等待池。

sleep()方法需要指定等待的时间,它可以让当前正在执行的线程在指定的时间内暂停执行,进入阻塞状态,该方法既可以让其他同优先级或者高优先级的线程得到执行的机会,也可以让低优先级的线程得到执行机会。但是sleep()方法不会释放“锁标志”,也就是说如果有synchronized同步块,其他线程仍然不能访问共享数据。

总结

等待-通知机制是一种非常普遍的线程间协作的方式。在使用 轮询的方式来等待某个状态的时候,可以使用等待-通知机制来进行优化。

转载地址:http://knkws.baihongyu.com/

你可能感兴趣的文章
Mysql出现Table 'performance_schema.session_status' doesn't exist
查看>>
MySQL innert join、left join、right join等理解
查看>>
vivado模块封装ip/edf
查看>>
sdc时序约束
查看>>
Xilinx Jtag Access/svf文件/BSCANE2
查看>>
NoC片上网络
查看>>
开源SoC整理
查看>>
【2020-3-21】Mac安装Homebrew慢,解决办法
查看>>
influxdb 命令行输出时间为 yyyy-MM-dd HH:mm:ss(年月日时分秒)的方法
查看>>
已知子网掩码,确定ip地址范围
查看>>
判断时间或者数字是否连续
查看>>
docker-daemon.json各配置详解
查看>>
Mac 下docker路径 /var/lib/docker不存在问题
查看>>
Docker(一)使用阿里云容器镜像服务
查看>>
Docker(二) 基础命令
查看>>
Docker(三) 构建镜像
查看>>
Spring 全家桶注解一览
查看>>
JDK1.8-Stream API使用
查看>>
cant connect to local MySQL server through socket /tmp/mysql.sock (2)
查看>>
vue中的状态管理 vuex store
查看>>