JavaEE: wait和notify

wait和notify(都需要搭配synchronized使用)

join(),哪个线程调用这个方法,哪个线程就堵塞

wait和notify都是Object的方法,随便定义一个对象都可以使用

wait、sleep、join的区别:

wait:需要搭配synchronized使用,线程wait处于WAITING状态;需要其它线程notify唤醒;也可设置时间到点唤醒

sleep:到时间才能被苏醒,也可以被interrupt中止,但会抛异常,非常规

join:谁调用join,当前线程就得停下来,等待调用join方法的这个线程执行完全部才可以执行;也可设置参数,到时间就可以不等了。

wait():

执行之前要做三件事:

1.释放当前的锁

2.让线程进入阻塞状态

3.当线程被唤醒的时候,重新获取到锁。

java 复制代码
//wait()
public class Demo22 {
    public static void main(String[] args) throws InterruptedException {
//        Object object = new Object();
//        System.out.println("wait之前:");
//        object.wait();//释放锁的前提是得有锁,不然会产生不合法监视器状态异常
//        System.out.println("wait之后: ");


        Object object = new Object();
        System.out.println("wait之前:");
        synchronized(object) {
            object.wait();
            //把 wait 要放到 synchronized 里面来调用. 保证确实是拿到锁了的.
            //wait() 先释放锁,再让线程进入阻塞状态,最后等待唤醒重新获取到锁
        }
        System.out.println("wait之后: ");

    }
}

wait和notify():可以用来避免"线程饿死"

wait的使用必须是当前对象被上锁之后才能使用(没上锁的话就不知道在wait谁了)

线程wait之后,必须要有其它线程notify来唤醒这个线程,不然会一直堵塞。

1.没有上锁的wait

2.没有其它线程来notify正在wait的线程

3.两个线程,一个wait,一个用notify来唤醒正在wait的线程

java 复制代码
package thread;

public class Demo23 {
    public static void main(String[] args) {
        Object object = new Object();
        Thread t1 = new Thread(() -> {
            synchronized (object) {
                System.out.println("wait之前:");
                try {
                    object.wait();
     //可以添加等待的时间,不会死等,超过等待时间就会去掉wait,继续向下执行
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
            System.out.println("wait之后: ");
        });

        Thread t2 = new Thread(() -> {
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            synchronized (object) {//可重复锁
                System.out.println("t2进行通知之前:");
                object.notify();
//唤醒,如果有多个线程需要唤醒,可以用notifyAll(),
//不过notify更为可控,唤醒之后,各个线程重新获取锁的过程是串行执行的、
                System.out.println("t2进行通知之后:");
            }

        });
        t1.start();
        t2.start();
    }
}

**注意:**释放wait的notify的锁对象要和wait的锁对象一样,不然不能释放,不能唤醒。

在系统中,notify可以不用上锁;

但在java中,规定要上锁。上锁对象和notify对象要一致,和系统有区别。

上述代码解析:

  1. 因为t2睡了3秒,所以t1线程先执行,打印"wait之前",然后t1线程堵塞等待。

  2. t2睡了3秒之后,获得locker锁,打印"t2进行通知之前:";

当t2线程执行notify之后,t1线程wait释放

  1. t2还持有锁,t1还在阻塞,打印"t2进行通知之后",释放锁

  2. t1拿到锁,打印"wait之后"

相关推荐
杨杨杨大侠2 小时前
都能接模型、RAG 和 MCP,Java Agent 框架到底差在哪?
java
破茧蝴蝶2 小时前
Python分布式爬虫完整教程
开发语言·python
狗凯之家源码网3 小时前
全新 PHP 轻量客服聊天室源码深度评测
开发语言·php·聊天室系统
远离UE43 小时前
UE5 Substrate Thin Film 源码拆析
开发语言·javascript·ue5
keyipatience3 小时前
JavaScript学习(1)书写位置,变量、数据类型、运算符
开发语言·前端·javascript·css·学习
Thinker QAQ3 小时前
并发编程(九):BlockingQueue 与 Channel——语言层的原子性、可见性与有序性
java·python·go·并发编程·channel·blockingqueue·message passing
栈帧之外4 小时前
【C++】STL之set
开发语言·c++
霸道流氓气质5 小时前
RAG 可观测性与生产监控实战:四层遥测模型、五大仪表盘与 OpenTelemetry 全链路追踪的 Java 生产级实现
java·人工智能·python
AOI小白新手上路5 小时前
autodl常用的tar 打包下载(数据集)命令手册:逐段拆解与套用模板
java·大数据·数据库
catchadmin5 小时前
免费可商用 PHP 管理后台 CatchAdmin V5.4.1 发布,新增 MCP 支持
开发语言·php