搜索
首页Javajava教程Java中sleep和wait方法有什么区别

    一、sleep和wait方法的区别

    • 根本区别:sleep是Thread类中的方法,不会马上进入运行状态,wait是Object类中的方法,一旦一个对象调用了wait方法,必须要采用notify()和notifyAll()方法唤醒该进程

    • 释放同步锁:sleep会释放cpu,但是sleep不会释放同步锁的资源,wait会释放同步锁资源

    • 使用范围: sleep可以在任何地方使用,但wait只能在synchronized的同步方法或是代码块中使用

    • 异常处理: sleep需要捕获异常,而wait不需要捕获异常

    二、wait方法

    • 使当前执行代码的线程进行等待. (把线程放到等待队列中)

    • 释放当前的锁

    • 满足一定条件时被唤醒, 重新尝试获取这个锁.

    • wait 要搭配 synchronized 来使用,脱离 synchronized 使用 wait 会直接抛出异常.

    wait方法的使用

    wait方法

    /**
     * wait的使用
     */
    public class WaitDemo1 {
        public static void main(String[] args) {
            Object lock = new Object();
            Thread t1 = new Thread(() -> {
                System.out.println("线程1开始执行");
                try {
                    synchronized (lock) {
                        System.out.println("线程1调用wait方法....");
                        // 无限期的等待状态
                        lock.wait();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("线程1执行完成");
            }, "线程1");
            t1.start();
        }
    }

    有参wait线程和无参wait线程

    /**
     * 有参wait线程和无参wait线程
     */
    public class WaitDemo2 {
        public static void main(String[] args) {
            Object lock1 = new Object();
            Object lock2 = new Object();
            Thread t1 = new Thread(()->{
                System.out.println("线程1开始执行");
                synchronized (lock1){
                    try {
                        lock1.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("线程1执行完成");
                }
            },"无参wait线程");
            t1.start();
            Thread t2 = new Thread(()->{
                System.out.println("线程2开始执行");
                synchronized (lock2){
                    try {
                        lock2.wait(60*60*1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("线程2执行完成");
                }
            },"有参wait线程");
            t2.start();
        }
    }

    wait结束等待的条件

    ①其他线程调用该对象的 notify 方法.

    ②wait 等待时间超时 (wait 方法提供一个带有 timeout 参数的版本, 来指定等待时间).

    ③其他线程调用该等待线程的 interrupted 方法, 导致 wait 抛出 InterruptedException 异常

    三、notify和notifyAll方法

    notify 方法只是唤醒某一个等待的线程

    1. 方法notify()也要在同步方法或同步块中调用,该方法是用来通知那些可能等待该对象的对象锁的其它线程

    2. 如果有多个线程等待,随机挑选一个wait状态的线程

    3. 在notify()方法后,当前线程不会马上释放该对象锁,要等到执行notify()方法的线程将程序执行完,也就是退出同步代码块之后才会释放对象锁

    notify方法的使用

    /**
     * wait的使用, 如果有多个线程等待,随机挑选一个wait状态的线程
     */
    public class WaitNotifyDemo {
        public static void main(String[] args) {
            Object lock1 = new Object();
            Object lock2 = new Object();
            Thread t1 = new Thread(()->{
                System.out.println("线程1开始执行");
                try {
                    synchronized (lock1) {
                        System.out.println("线程1调用wait方法");
                        lock1.wait();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("线程1执行完成");
            },"线程1");
            Thread t2 = new Thread(()->{
                System.out.println("线程2开始执行");
                try {
                    synchronized (lock1) {
                        System.out.println("线程2调用wait方法");
                        lock1.wait();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("线程2执行完成");
            },"线程2");
            t1.start();
            t2.start();
            // 唤醒 lock1 对象上休眠的线程的(随机唤醒一个)
            Thread t3 = new Thread(()->{
                try {
                    Thread.sleep(1500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("线程3开始执行");
                synchronized (lock1){
                    //发出唤醒通知
                    System.out.println("执行了唤醒");
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            },"线程3");
            t3.start();
        }
    }

    notifyAll方法可以一次唤醒所有的等待线程

    notifyAll方法的使用

    /**
     * notifyAll-唤醒所有线程
     */
    public class WaitNotifyAll {
        public static void main(String[] args) {
            Object lock = new Object();
    
            new Thread(() -> {
                System.out.println("线程1:开始执行");
                synchronized (lock) {
                    try {
                        lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("线程1:执行完成");
                }
            }, "无参wait线程").start();
    
            new Thread(() -> {
                synchronized (lock) {
                    System.out.println("线程2:开始执行 |" + LocalDateTime.now());
                    try {
                        lock.wait(60 * 60 * 60 * 1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("线程2:执行完成 | " + LocalDateTime.now());
                }
            }, "有参wait线程").start();
    
            new Thread(() -> {
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (lock) {
                    System.out.println("唤醒所有线程");
                    lock.notifyAll();
                }
            }).start();
        }
    }

    notify和notifyAll方法的区别

    1. 当你调用notify时,只有一个等待线程会被唤醒而且它不能保证哪个线程会被唤醒,这取决于线程调度器。

    2. 调用notifyAll方法,那么等待该锁的所有线程都会被唤醒,但是在执行剩余的代码之前,所有被唤醒的线程都将争夺锁定,这就是为什么在循环上调用wait,因为如果多个线程被唤醒,那么线程是将获得锁定将首先执行,它可能会重置等待条件,这将迫使后续线程等待。

    3. 因此,notify和notifyAll之间的关键区别在于notify()只会唤醒一个线程,而notifyAll方法将唤醒所有线程。

    以上是Java中sleep和wait方法有什么区别的详细内容。更多信息请关注PHP中文网其他相关文章!

    声明
    本文转载于:亿速云。如有侵权,请联系admin@php.cn删除

    热AI工具

    Undresser.AI Undress

    Undresser.AI Undress

    人工智能驱动的应用程序,用于创建逼真的裸体照片

    AI Clothes Remover

    AI Clothes Remover

    用于从照片中去除衣服的在线人工智能工具。

    Undress AI Tool

    Undress AI Tool

    免费脱衣服图片

    Clothoff.io

    Clothoff.io

    AI脱衣机

    AI Hentai Generator

    AI Hentai Generator

    免费生成ai无尽的。

    热门文章

    R.E.P.O.能量晶体解释及其做什么(黄色晶体)
    1 个月前By尊渡假赌尊渡假赌尊渡假赌
    R.E.P.O.最佳图形设置
    1 个月前By尊渡假赌尊渡假赌尊渡假赌
    威尔R.E.P.O.有交叉游戏吗?
    1 个月前By尊渡假赌尊渡假赌尊渡假赌

    热工具

    SecLists

    SecLists

    SecLists是最终安全测试人员的伙伴。它是一个包含各种类型列表的集合,这些列表在安全评估过程中经常使用,都在一个地方。SecLists通过方便地提供安全测试人员可能需要的所有列表,帮助提高安全测试的效率和生产力。列表类型包括用户名、密码、URL、模糊测试有效载荷、敏感数据模式、Web shell等等。测试人员只需将此存储库拉到新的测试机上,他就可以访问到所需的每种类型的列表。

    SublimeText3汉化版

    SublimeText3汉化版

    中文版,非常好用

    禅工作室 13.0.1

    禅工作室 13.0.1

    功能强大的PHP集成开发环境

    Atom编辑器mac版下载

    Atom编辑器mac版下载

    最流行的的开源编辑器

    MinGW - 适用于 Windows 的极简 GNU

    MinGW - 适用于 Windows 的极简 GNU

    这个项目正在迁移到osdn.net/projects/mingw的过程中,你可以继续在那里关注我们。MinGW:GNU编译器集合(GCC)的本地Windows移植版本,可自由分发的导入库和用于构建本地Windows应用程序的头文件;包括对MSVC运行时的扩展,以支持C99功能。MinGW的所有软件都可以在64位Windows平台上运行。