• wait与notify的使用


    🎈专栏链接:多线程相关知识详解

    wait是Object类里面的方法,而Object类是所有类的父类,所以所有的类都可以使用wait方法

    wait里面包含着3个操作:

    ①释放当前锁

    ②进入阻塞等待

    ③其他线程调用notify的时候,可以将其唤醒并尝试重新获取锁

    1. public class Demo2 {
    2. public static void main(String[] args) {
    3. Object object = new Object();
    4. Thread t1 = new Thread(() -> {
    5. while (true){
    6. synchronized (object){
    7. try {
    8. System.out.println("wait之前");
    9. object.wait();//线程阻塞等待
    10. } catch (InterruptedException e) {
    11. throw new RuntimeException(e);
    12. }
    13. //下面的代码只能在notify唤醒线程之后才能执行
    14. System.out.println("wait之后");
    15. }
    16. }
    17. });
    18. t1.start();
    19. try {
    20. Thread.sleep(500);//确保上面这个线程已经进行阻塞等待,防止上面的线程与下面的线程发生抢占式执行
    21. } catch (InterruptedException e) {
    22. throw new RuntimeException(e);
    23. }
    24. Thread t2 = new Thread(() -> {
    25. while (true){
    26. synchronized (object){
    27. System.out.println("notify之前");
    28. object.notify();
    29. System.out.println("notify之后");
    30. }
    31. try {
    32. Thread.sleep(5000);
    33. } catch (InterruptedException e) {
    34. throw new RuntimeException(e);
    35. }
    36. }
    37. });
    38. t2.start();
    39. }
    40. }

    wait和notify能够控制多线程之间的执行先后顺序

    wait和notify使用时需要注意的四点:

    1.都要搭配synchronized来进行使用

    2.wait和notify得使用同一个对象,才是有效的

    3.用来加锁的对象和wait/notify对象也得一致

    4.即使当前没有线程在wait,直接notify也不会有副作用

    当有多个线程wait等待的时候,由于线程的抢占式执行,所以notify所唤醒的线程是不确定的,需要看系统调度,除非是多个不同对象的wait,使用不同对象的notify,各自唤醒各自的,如果是一个对象在好几个线程里都wait,不能指定唤醒也可以直接使用notifyAll方法直接将所有的线程直接唤醒

    wait还有一个重载版本,参数可以传时间,表示等待的最大时间,下面这个代码是该方法的源代码

    timeout – the maximum time to wait in milliseconds.(以毫秒为单位的最大等待时间)

    nanos – additional time, in nanoseconds range 0-999999.(额外时间,以纳秒为单位,范围为0-999999)

    1. public final void wait(long timeout, int nanos) throws InterruptedException {
    2. if (timeout < 0) {
    3. throw new IllegalArgumentException("timeout value is negative");
    4. }
    5. if (nanos < 0 || nanos > 999999) {
    6. throw new IllegalArgumentException(
    7. "nanosecond timeout value out of range");
    8. }
    9. if (nanos > 0) {
    10. timeout++;
    11. }
    12. wait(timeout);
    13. }
  • 相关阅读:
    ES数据库的使用
    centos7安装mysql8
    如何确定自己是否适合做程序员?
    SPA项目实现首页导航以及左侧菜单
    肖sir__mysql中数据库后端无法展示
    C#基于asp.net的社区团购网站
    Servlet
    Java语言在Spark3.2.4集群中使用Spark MLlib库完成朴素贝叶斯分类器
    android 性能优化
    JavaSE——String类常用方法详解(玩转字符串)
  • 原文地址:https://blog.csdn.net/qq_62949535/article/details/127112545