Java详细分析sleep和wait方法有哪些区别

发布时间:2023-10-17 18:30

目录
  • 一、sleep和wait方法的区别
  • 二、wait方法
    • wait方法的使用
    • wait结束等待的条件
  • 三、notify和notifyAll方法

    一、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方法有哪些区别的文章就介绍到这了,更多相关Java sleep与wait内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

    ItVuer - 免责声明 - 关于我们 - 联系我们

    本网站信息来源于互联网,如有侵权请联系:561261067@qq.com

    桂ICP备16001015号