Marvel-Site Marvel-Site
首页
  • Java

    • Java基础
    • Java进阶
    • Java容器
    • Java并发编程
    • Java虚拟机
  • 计算机基础

    • 数据结构与算法
    • 计算机网络
    • 操作系统
    • Linux
  • 框架|中间件

    • Spring
    • MySQL
    • Redis
    • MQ
    • Zookeeper
    • Git
  • 架构

    • 分布式
    • 高并发
    • 高可用
    • 架构
  • 框架

    • React
    • 其他
  • 实用工具
  • 安装配置

    • Linux
    • Windows
    • Mac
  • 开发工具

    • IDEA
    • VsCode
  • 关于
  • 收藏
  • 草稿
  • 索引

    • 分类
    • 标签
    • 归档
GitHub (opens new window)

Marvel

吾必当乘此羽葆盖车
首页
  • Java

    • Java基础
    • Java进阶
    • Java容器
    • Java并发编程
    • Java虚拟机
  • 计算机基础

    • 数据结构与算法
    • 计算机网络
    • 操作系统
    • Linux
  • 框架|中间件

    • Spring
    • MySQL
    • Redis
    • MQ
    • Zookeeper
    • Git
  • 架构

    • 分布式
    • 高并发
    • 高可用
    • 架构
  • 框架

    • React
    • 其他
  • 实用工具
  • 安装配置

    • Linux
    • Windows
    • Mac
  • 开发工具

    • IDEA
    • VsCode
  • 关于
  • 收藏
  • 草稿
  • 索引

    • 分类
    • 标签
    • 归档
GitHub (opens new window)
  • Java

    • Java基础

    • Java进阶

    • Java容器

    • Java并发编程

      • 并发编程基本概念
      • 多线程
      • 创建多线程的方法
      • 比较与交换CAS
      • Java对象头与Monitor监视器
      • Java主流锁
      • synchronized关键字
      • volatile关键字
      • 线程池
      • 原子类Atomic
      • LockSupport工具
      • 抽象队列同步器AQS
      • ThreadLocal深度理解
      • 多线程循环打印代码
      • 线程等待和唤醒的三种方式
        • 1. wait&notify
        • 2 await&signal
        • 3 park&unpark
      • ReentrantLock非公平锁的源码分析
    • Java虚拟机

    • 常见面试题

  • 计算机基础

  • 框架|中间件

  • 架构

  • 后端
  • Java
  • Java并发编程
Marvel
2022-07-19
目录

线程等待和唤醒的三种方式

# 线程等待和唤醒的三种方式

# 1. wait&notify

使用Object种的wait()方法让线程等待,使用Object中的notify()方法唤醒线程。

public class LockSupportDemo {
    static Object objectLock = new Object();

    public static void main(String[] args) {
        new Thread(() -> {
            synchronized (objectLock) {
                System.out.println(Thread.currentThread().getName() + "\t" + "---come in!");
                objectLock.wait();
                System.out.println(Thread.currentThread().getName() + "\t" + "---被唤醒!");
            }
        }, "A").start();
        new Thread(() -> {
            synchronized (objectLock) {
                objectLock.notify();
                System.out.println(Thread.currentThread().getName() + "\t" + "---通知!");
            }
        }, "B").start();
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

注意:

  1. wait 和 notify 不能脱离 synchronized 代码块,会出现 java.lang.IllegalMonitorStateException 异常

  2. 先 notify 再 wait,notify 就起不到任何效果。必须要先等待后唤醒,线程才能被唤醒。

# 2 await&signal

使用JUC包中的 Condition 的 await() 方法让线程等待,使用 signal() 方法唤醒线程。

public class LockSupportDemo {
    static Lock lock = new ReentrantLock();
    static Condition condition = lock.newCondition();

    public static void main(String[] args) {
        new Thread(() -> {
            lock.lock();
            try {
                System.out.println(Thread.currentThread().getName() + "\t" + "---come in!");
                try {
                    condition.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "\t" + "---被唤醒!");
            } finally {
                lock.unlock();
            }
        }, "A").start();

        new Thread(() -> {
            lock.lock();
            try {
                condition.signal();
                System.out.println(Thread.currentThread().getName() + "\t" + "---通知!");
            } finally {
                lock.unlock();
            }
        }, "B").start();
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

注意:

  1. condition.await() 和 condition.signal() 要与成对的 lock() 与 unlock() 使用,否则会报java.lang.IllegalMonitorStateException异常
  2. 先 signal 再 await,signal 不起作用。必须要先等待后唤醒,线程才能被唤醒。

# 3 park&unpark

LockSupport 类可以阻塞当前线程以及缓存指定被阻塞的线程。

public class LockSupportDemo {
    public static void main(String[] args) {
        Thread t1 = new Thread(() -> {
            System.out.println(Thread.currentThread().getName() + "\t" + "---come in!");
            LockSupport.park(); // 阻塞,等待通知放行,它需要许可证
            System.out.println(Thread.currentThread().getName() + "\t" + "---被唤醒!");

        }, "A");
        t1.start();

        Thread t2 = new Thread(() -> {
            System.out.println(Thread.currentThread().getName() + "\t" + "---通知!");
            LockSupport.unpark(t1);
        }, "B");
        t2.start();
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

注意:

  1. 与前面相比,不需要锁块。
  2. 可以先 unpark 再 park。先执行 unpark() 会导致 park() 方法形同虚设。
编辑 (opens new window)
#Java#JUC
上次更新: 2023/08/20, 21:21:52
多线程循环打印代码
ReentrantLock非公平锁的源码分析

← 多线程循环打印代码 ReentrantLock非公平锁的源码分析→

最近更新
01
位运算
05-21
02
二叉树
05-12
03
Spring三级缓存解决循环依赖
03-25
更多文章>
Theme by Vdoing | Copyright © 2022-2024 Marvel
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式