美文网首页
线程的 sleep() 方法与 wait() 方法的区别

线程的 sleep() 方法与 wait() 方法的区别

作者: 分布式与微服务 | 来源:发表于2022-11-03 09:01 被阅读0次

    总的来说,线程的 sleep() 方法和 wait() 方法有以下几点区别:

    (1)sleep() 方法是 Thread 类中的方法,而 wait() 方法是 Object 类中的方法。

    (2)sleep() 方法不会释放 lock,但是 wait() 方法会释放,而且会加入到等待队列中。

    (3)sleep() 方法不依赖于同步器 synchronized(),但是 wait() 方法 需要依赖 synchronized 关键字。

    (4)线程调用 sleep() 之后不需要被唤醒(休眠时开始阻塞,线程的监控状态依然保持着,当指定的休眠时间到了就会自动恢复运行状态),但是 wait() 方法需要被重新唤醒(不指定时间需要被别人中断)。

    public class SleepDemo {
     
        public static final Object LOCK = new Object();
     
        public static void main(String[] args) {
            Stream.of("线程1", "线程2").forEach(a -> new Thread(a) {
                @Override
                public void run() {
                    new SleepDemo().testSleep();
                }
            }.start());
        }
     
        private void testSleep() {
            synchronized (LOCK) {
                try {
                    System.out.println(Thread.currentThread().getName() + "正在执行: " + System.currentTimeMillis() / 1000);
                    // 休眠 2 s
                    Thread.sleep(2000);
                    System.out.println(Thread.currentThread().getName() + "恢复执行: " + System.currentTimeMillis() / 1000);
                } catch (Exception e) {
     
                }
            }
        }
     
    }
    

    可以看到,线程 1 先抢到了资源,执行主体方法时要求睡眠 2 秒,那么在这两秒时间内,即使线程 1 没有任何动作,线程 2 也不能抢占资源。 需要注意的是,在调用 sleep() 方法时,如果有两个线程,那么要想实现线程睡眠的效果就需要使用 synchronized() 方法,否则达不到效果。

    public class SleepDemo {
     
    //    public static final Object LOCK = new Object();
     
        public static void main(String[] args) {
            Stream.of("线程1", "线程2").forEach(a -> new Thread(a) {
                @Override
                public void run() {
                    new SleepDemo().testSleep();
                }
            }.start());
        }
     
        private void testSleep() {
    //        synchronized (LOCK) {
                try {
                    System.out.println(Thread.currentThread().getName() + "正在执行: " + System.currentTimeMillis() / 1000);
                    // 休眠 2 s
                    Thread.sleep(2000);
                    System.out.println(Thread.currentThread().getName() + "恢复执行: " + System.currentTimeMillis() / 1000);
                } catch (Exception e) {
                    System.out.println(e);
                }
    //        }
        }
     
    }
    

    如上所示,不使用 synchronized() 的话就会出现两个线程同时执行,同时睡眠,又同时恢复执行。

    由此可知,调用 sleep() 方法时,并不是强依赖于 synchronized() 方法,如果我只有一个线程,那么使用 synchronized() 方法和不使用 synchronized() 方法的效果是一样的。如果有两个线程的话,也可以选择使用或者不使用 synchronized() 方法。但是 wait() 方法就不一样了,wait() 方法强依赖于 synchronized() 方法,如果不使用 synchronized() 方法的话,wait() 方法的程序就会报错。

    public class WaitDemo {
     
        public static final Object LOCK = new Object();
     
        public static void main(String[] args) {
            Stream.of("线程1", "线程2").forEach(a -> new Thread(a) {
                @Override
                public void run() {
                    WaitDemo.testWait();
                }
            }.start());
        }
     
        private static void testWait() {
    //        synchronized (LOCK) {
                try {
                    System.out.println(Thread.currentThread().getName() + "正在执行: " + System.currentTimeMillis() / 1000);
                    // 等待 2 s
                    LOCK.wait(2000);
                    System.out.println(Thread.currentThread().getName() + "恢复执行: " + System.currentTimeMillis() / 1000);
                } catch (InterruptedException e) {
                    System.out.println(e);
                }
            }
    //    }
     
    }
    

    使用 synchronized 关键字修饰后:

    public class WaitDemo {
     
        public static final Object LOCK = new Object();
     
        public static void main(String[] args) {
            Stream.of("线程1", "线程2").forEach(a -> new Thread(a) {
                @Override
                public void run() {
                    WaitDemo.testWait();
                }
            }.start());
        }
     
        private static void testWait() {
            synchronized (LOCK) {
                try {
                    System.out.println(Thread.currentThread().getName() + "正在执行: " + System.currentTimeMillis() / 1000);
                    // 等待 2 s
                    LOCK.wait(2000);
                    System.out.println(Thread.currentThread().getName() + "恢复执行: " + System.currentTimeMillis() / 1000);
                } catch (InterruptedException e) {
                    System.out.println(e);
                }
            }
        }
     
    }
    

    因为在代码中有指定 wait(2000),所以当 2 秒之后该线程就会恢复执行的,而不用另外一个线程去唤醒,如果 wait() 方法没有指定时间的话,那么该线程就会一直等待~

    除此之外,一个线程一旦被 wait 之后,就必须有另外一个线程去唤醒,否则一直处于等待状态。

    public class WaitDemo {
     
        public static final Object LOCK = new Object();
     
        private void testWait1() {
            synchronized (LOCK) {
                try {
                    System.out.println(Thread.currentThread().getName() + "开始执行: " + System.currentTimeMillis() / 1000);
                    LOCK.wait();
                    System.out.println(Thread.currentThread().getName() + "恢复执行: " + System.currentTimeMillis() / 1000);
                } catch (Exception e) {
                    System.out.println(e);
                }
            }
        }
     
        private void testNotify() {
            synchronized (LOCK) {
                try {
                    Thread.sleep(2000);
                    LOCK.notify();
                    System.out.println(Thread.currentThread().getName() + "唤醒另一线程: " + System.currentTimeMillis() / 1000);
                } catch (Exception e) {
                    System.out.println(e);
                }
            }
        }
     
        public static void main(String[] args) {
            new Thread() {
                @Override
                public void run() {
                    new WaitDemo().testWait1();
                }
            }.start();
            new Thread() {
                @Override
                public void run() {
                    new WaitDemo().testNotify();
                }
            }.start();
        }
     
    }
    

    相关文章

      网友评论

          本文标题:线程的 sleep() 方法与 wait() 方法的区别

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