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

2年前 (2022) 程序员胖胖胖虎阿
240 0 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) {

            }
        }
    }

}

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

可以看到,线程 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);
            }
//        }
    }

}

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

如上所示,不使用 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);
            }
        }
//    }

}

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

使用 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);
            }
        }
    }

}

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

因为在代码中有指定 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() 方法的区别

 

 本文参考自:sleep() 和 wait() 的区别分析 - 掘金

版权声明:程序员胖胖胖虎阿 发表于 2022年9月18日 下午4:48。
转载请注明:线程的 sleep() 方法与 wait() 方法的区别 | 胖虎的工具箱-编程导航

相关文章

暂无评论

暂无评论...