美文网首页
Java多线程编程(3)等待和通知

Java多线程编程(3)等待和通知

作者: 景知育德 | 来源:发表于2022-12-11 18:02 被阅读0次

正如大学生返乡需要等通知一样,Java 的多线程编程同样可以“等通知”。
值得注意的是,wait/notify/notifyAll 是 Object 的方法,不是 Thread 的方法

简介

wait 方法让当前线程阻塞,直到 notify 或 notifyAll 才唤醒,或者超时自动唤醒。

例如

synchronized(X) {
    // ...
    X.wait(); // 注意是X
    // ...
    X.notifyAll();
    // ...
}

这里需要三个地方的X是同一对象。

我们同样可以用厕所隔间打比方,比如X就是某个厕所隔间,需要同步地使用厕所隔间(不能两个人同时用),故而需要synchronized来保证同步。没进去的,需要等,等的东西就是X,所以一般while循环体里等待,等好了,再使用厕所,使用完了,再通过notifyAll来告诉别人可以进厕所了。

wait 对比 sleep

wait可以设置一段时间,也就是最长的等待时间。而sleep也有一个参数是时间,故而二者有一些共同点。下面是二者的对比。

共同点

  1. 都会让线程进入阻塞状态

  2. 都可以打断,即抛出InterruptedException

  3. 都有时间长度这一个参数。

不同点

  1. wait 是 Object 的方法;sleep 是 Thread 的方法。

  2. wait 必须在同步的地方(即synchronized修饰的区域)使用;sleep 不需要如此。

  3. wait 会释放 monitor 锁,也就是说,你先拿到了厕所的锁,进去后发现要 wait,这个时候会释放掉厕所的所;sleep 不会释放掉 monitor 锁。

  4. wait 可以不设置时间,那样就会一直等待,直到被打断或者等好了。

模型

wait、notify 最常见的模型是生产者-消费者模型。一个队列,如果没有满,生产者就可以生产,如果满了,就需要 wait。如果队列还有东西,消费者就可以消费,如果空了,就需要 wait。

  • 如果总共只有两个线程,一个生产者,一个消费者,可以用 if + wait + notify

  • 如果有多个线程(不止两个),则必须用 while + wait + notifyAll

示例

下面我写了一个关于学生离校的模型。有三个学生准备离校。学校是否允许大学生离校,以一个布尔值保存在school.notification,如果学校不允许离校,即school.notification = false时,学生们只能干等着,直到学校允许,即school.notification = true

package org.example;

import java.util.concurrent.TimeUnit;

public class Study8WaitNotify {
    public static void main(String[] args) throws InterruptedException {
        School school = new School();
        school.notification = false;
        String[] names = {"张三", "李四", "王五"};
        Thread[] students = new Thread[names.length];
        for (int i = 0; i < names.length; i++) {
            students[i] = new Student(names[i], school);
            students[i].start();
        }
        TimeUnit.SECONDS.sleep(3);
        synchronized (school) {
            System.out.println("校长进入临界区");
            school.notification = true;
            System.out.println("校长说可以润了");
            school.notify();
        }
    }
}
class School {
    public boolean notification;
}

class Student extends Thread {
    private final String name; // 名字
    private final School school; // 学校

    public Student(String name, School school) {
        this.name = name;
        this.school = school;
    }

    public void leaveSchool() {
        System.out.println(name + "润掉了");
    }

    // 重载润
    @Override
    public void run() {
        System.out.println(name + "开始润");
        synchronized (school) {
            System.out.println(name + "进入临界区");
            while (!school.notification) { // ① 这里是是真正在等待的
                try {
                    System.out.println(name + "发现润不掉");
                    school.wait(); // ② 书写 wait 的位置
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
            leaveSchool();
            school.notify();
        }
    }
}

注意到注释①和注释②的地方,我们虽然在②处写了school.wait(),但是我们真正在等的是school.notification

相关文章

  • Java多线程编程(3)等待和通知

    正如大学生返乡需要等通知一样,Java 的多线程编程同样可以“等通知”。值得注意的是,wait/notify/no...

  • Java并发编程 - LockSupport

    Java并发编程 - 等待/通知 我们知道Java语言的Object类中提供了wait、notify和notify...

  • 《Java 多线程精选》思维导图

    本文主要分析了 Java 多线程的精选内容 1.进程和线程 2.Java 多线程编程入门 3.线程组和线程优先级 ...

  • Java多线程学习:Future、Callable

    Java多线程编程:Callable、Future和FutureTask浅析(多线程编程之四) 最近在写清结算文件...

  • 第四章 并发编程基础

    线程的状态。如何启动和终止线程。多线程之间通信的基本方式。多线程编程的等待/通知的经典范式。 现代操作系统调度的最...

  • Java socket

    Java Socket实现基于TCP和UDP多线程通信Java Socket编程

  • 等待和通知

    等待和通知 API java.lang.Object 类提供了一套等待/通知的 API,它由 3 个 wait()...

  • Java并发编程 - 等待/通知

    Java语言为线程的通信提供了支持,其中的一种方式就是等待/通知机制,java.lang.Object的wait、...

  • 多线程:3线程间通信

    线程间通信:《多线程编程核心技术》笔记 1.等待/通知机制 1.1什么是等待通知机制 1.厨师做完一道菜的时间不确...

  • 2018-10-16

    Java编程思想 1~12 java多线程编程核心技术 23~57

网友评论

      本文标题:Java多线程编程(3)等待和通知

      本文链接:https://www.haomeiwen.com/subject/asgfqdtx.html