wait 和notify ,notifyAll,sleep

wait

使线程进入阻塞状态,释放CPU,以及锁

sleep

使线程进入睡眠状态,sleep方法不会释放CPU资源和锁资源,而是让出CPU的使用权。操作系统会将CPU分配给其他就绪线程,但当前线程依然存在,不会释放其占用的内存或其他资源。当调用Thread.sleep(milliseconds)时,当前线程会从"运行状态(RUNNABLE)"进入"计时等待状态(TIMED_WAITING)"。线程并没有被销毁,只是暂时停止执行,等待指定时间后重新进入就绪队列,等待CPU调度

notify

随机唤醒一个阻塞的线程

notifyAll

唤醒全部阻塞的线程

实现一个方法:两个线程交替打印奇数和偶数到100,线程A打印奇数,线程B打印偶数,交替打印

两个线程同时开始抢锁,如果是奇数线程抢到了锁,奇数线程判断当前是不是奇数,偶数线程判断当前是不是偶数

  • 第一次:如果偶数线程抢到了锁,但是不是偶数,就直接当前线程wait,释放锁,让奇数线程获取到锁,
  • 奇数执行打印数字,并给数字加1,然后唤醒其他线程(偶数数线程),此时奇数线程还拥有着锁,于是在此判断当前线
    数字是不是奇数,不是就执行wait方法,释放锁。
  • 此时偶数线程就可以获取到锁,然后执行完之后,数字加一,然后唤醒奇数线程,
  • 此时同样的,偶数线程还有锁,于是再次进入方法,判断是不是偶数,不是,就执行wait方法,释放锁
  • 然后奇数线程获取到锁,执行
  • 这样交互执行到数值达到100就终止,break
  • 三个要素:
复制代码
  第一步:while循环判断当前数字是否小于等于100,
复制代码
  第二步:尝试获取到锁
复制代码
  第三步: 根据数字是奇数还是偶数判断,是打印数字,并累加,然后唤醒其他线程,还是当前线程直接wait方法,释放锁
java 复制代码
public class AlternatePrinting {
    private static final int MAX_NUMBER = 100;
    private static int currentNumber = 1;
    private static final Object lock = new Object();

    public static void main(String[] args) {
        Thread oddThread = new Thread(() -> {
            while (currentNumber <= MAX_NUMBER) {
                synchronized (lock) {
                    // // 让偶数线程打印,且未超过最大值
                    while (currentNumber <= MAX_NUMBER && currentNumber % 2 != 1) {
                        try {
                            //当前线程使当前线程进入等待状态,并且释放锁
                            lock.wait();
                        } catch (InterruptedException e) {
                            Thread.currentThread().interrupt();
                        }
                    }
                    if (currentNumber > MAX_NUMBER) break;
                    System.out.println("Odd: " + currentNumber++);
                    lock.notifyAll(); // 唤醒偶数线程
                }
            }
        });

        Thread evenThread = new Thread(() -> {
            while (currentNumber <= MAX_NUMBER) {
                synchronized (lock) {
                    // 让奇数线程打印,且未超过最大值
                    while (currentNumber <= MAX_NUMBER && currentNumber % 2 == 1) {
                        try {
                            lock.wait(); // 等待奇数线程打印后唤醒
                        } catch (InterruptedException e) {
                            Thread.currentThread().interrupt();
                        }
                    }
                    if (currentNumber > MAX_NUMBER) break;
                    System.out.println("Even: " + currentNumber++);
                    lock.notifyAll(); // 唤醒奇数线程
                }
            }
        });

        oddThread.start();
        evenThread.start();
    }
}
相关推荐
蛋蛋的就会顺顺的5 小时前
hot100 p0——栈,贪心算法,动态规划
java·前端·javascript·算法·leetcode·力扣
需要8265 小时前
Spring Bean 生命周期:从实例化到销毁的完整钩子
java·后端·spring
小 黄 鸡5 小时前
HashMap 面试必会知识点详解(JDK 8)
java·面试·职场和发展
死磕音视频6 小时前
让小模型做选择题:限定候选项并读取 logits 概率的入门实践(附 Python 代码)
开发语言·python·大模型·文本分类·transformers
伯恩bourne7 小时前
Spring Boot Bean 注册的两种方式:@Component 家族 vs @Configuration + @Bean
java·spring boot·后端
silvamux_8 小时前
curl 测试 OpenAI 兼容 API 的完整流程
java·人工智能·缓存·ai·oneapi
省钱兄--zs8 小时前
深圳24小时自助健身房软硬件解决方案实战指南与开发流程详解
java·数据仓库·spring boot·小程序·架构
顽疲8 小时前
Java vue 养老系统源码详解:月账单 care_month_bill 与 Quartz 扣费 Job 实践
java·开发语言·vue.js·vue养老·springboot养老·java养老
Wang's Blog9 小时前
Java 项目实战: 交友项目 - 安装开发工具与环境准备
java·开发语言·交友
用户21296835261689 小时前
开源了一个 Java 多智能体 LLM 框架 Baton:一个依赖,把 Agent 循环、工具调用、记忆、编排全配齐
java·llm