本文主要是介绍【多线程】并发编程wait和sleep的区别,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
notyfy、notifyAll、wait的使用:sleep/wait/notify/notifyAll分别有什么作用
背景:之前的博客讲解到了notify的使用,那并发编程的时候,到底该用 sleep还是notify呢?本篇我们来一起梳理一下区别
- 所属类与方法类型
- wait():wait方法是Object类的一个方法。它用于线程间的通信,允许一个线程等待另一个线程的通知(通过notify()或notifyAll()方法)来继续执行。
- sleep():sleep是Thread类的一个静态方法。它用于暂停当前线程的执行一段时间,但不会释放对象锁。
-
锁释放
wait():调用wait()方法的线程会释放它持有的对象锁,并进入等待状态,直到其他线程调用该对象的notify()或notifyAll()方法来唤醒它。
sleep():调用sleep()方法的线程不会释放它持有的任何锁。它只是在当前线程的执行路径上暂停一段时间。 -
使用场景
wait():wait通常用于线程间的交互和通信,特别是在需要等待某个条件成立时。它要求调用线程必须拥有对象的锁。
sleep():sleep常用于暂停线程执行一段时间,例如,模拟延时、减少CPU占用等。它不要求调用线程拥有任何对象的锁。 -
唤醒机制
wait():wait()方法被调用后,可以通过其他线程调用该对象的notify()或notifyAll()方法来唤醒。
sleep():sleep()方法睡眠指定时间之后,线程会自动苏醒,或者通过调用interrupt()方法提前打断睡眠。 -
调用位置
wait():wait()方法必须在同步方法或同步代码块中调用,因为它要求调用线程必须拥有对象的锁。否则,会抛出IllegalMonitorStateException异常。
sleep():sleep()方法可以在任何地方调用,因为它不涉及对象锁的释放和获取。 -
返回值与异常
wait():wait()方法不返回任何值,并且在等待过程中可能会抛出InterruptedException异常。
sleep():sleep(long millis)方法也不返回任何值,但在等待过程中同样可能会抛出InterruptedException异常。
总结
sleep和wait都可以让线程阻塞,也都可以指定超时时间,甚至还都会抛出中断异常InterruptedException。
而它们最大的区别就在于,sleep时线程依然持有锁,别人无法进当前同步方法;wait时放弃了持有的锁,其它线程有机会进入该同步方法。多次提到同步方法,因为wait必须在synchronized同步代码块中,否则会抛出异常IllegalMonitorStateException,notify也是如此,可以说wait和notify是就是为了在同步代码中做线程调度而生的
简单的例子展现sleep和wait的区别
package com.atguigu.signcenter.thread;import lombok.extern.slf4j.Slf4j;import java.util.Date;
import java.util.concurrent.atomic.AtomicInteger;/**** sleep和wait的区别* @author: jd* @create: 2024-09-02*/
@Slf4j
public class ThreadSleepAndWait {// 日志行号记录private AtomicInteger count = new AtomicInteger();public static void main(String[] args) throws InterruptedException {ThreadSleepAndWait threadSleepAndWait = new ThreadSleepAndWait();Thread t1 = new Thread(()->{try {threadSleepAndWait.test();} catch (InterruptedException e) {e.printStackTrace();}});Thread t2 =new Thread(()->{try {threadSleepAndWait.test();} catch (InterruptedException e) {e.printStackTrace();}});t1.start();t2.start();}/*** sleep 和 notify的区别*/private synchronized void test() throws InterruptedException {log("进入了同步方法,并开始睡觉sleep,3s");// sleep不会释放锁,因此其他线程不能进入这个test()方法,所以另外一个线程不会输出“进入了同步方法,并开始睡觉 这个提示”Thread.sleep(3000);log("sleep完成,释放掉锁,接着wait等待5s");//wait阻塞在此,因为他会释放锁,其它线程可以进入这个方法//当其它线程调用此对象的notify或者notifyAll时才有机会停止阻塞//就算没有人notify,如果超时了也会停止阻塞//在下面这行代码执行之后,另外一个线程才会进来test()方法log("wait(5000)等待执行之前,这里当前执行的线程释放掉锁,所以另外一个线程就能进行进入这个方法开始执行了" +",同时新线程开始wait(5000)");wait(2000);log("wait(5000)等待执行之后"); //这里thread0释放了锁并开始等待,所以Thread-1抢到了执行权,就开始打印最开始的提示log("我要走了,但我要再睡一觉sleep(10000),10s");//这里睡的时间很长,因为没有释放锁,其它线程就算wait超时了也无法继续执行Thread.sleep(10000);log("走了,调用notify方法,停止对当前同一个threadSleepAndWait对象的wait阻塞,对他进行唤醒");
// notify();}// 打印日志private void log(String s) {System.out.println(count.incrementAndGet() + " "+ new Date().toString().split(" ")[3]+ "\t" + Thread.currentThread().getName() + " " + s);}
}
结果(无解析):
1 17:04:20 Thread-0 进入了同步方法,并开始睡觉sleep,3s
2 17:04:23 Thread-0 sleep完成,释放掉锁,接着wait等待5s
3 17:04:23 Thread-0 wait(5000)等待执行之前,这里当前执行的线程释放掉锁,所以另外一个线程就能进行进入这个方法开始执行了,同时新线程开始wait(5000)
4 17:04:23 Thread-1 进入了同步方法,并开始睡觉sleep,3s
5 17:04:26 Thread-1 sleep完成,释放掉锁,接着wait等待5s
6 17:04:26 Thread-1 wait(5000)等待执行之前,这里当前执行的线程释放掉锁,所以另外一个线程就能进行进入这个方法开始执行了,同时新线程开始wait(5000)
7 17:04:28 Thread-0 wait(5000)等待执行之后
8 17:04:28 Thread-0 我要走了,但我要再睡一觉sleep(10000),10s
9 17:04:38 Thread-0 走了,调用notify方法,停止对当前同一个threadSleepAndWait对象的wait阻塞,对他进行唤醒
10 17:04:38 Thread-1 wait(5000)等待执行之后
11 17:04:38 Thread-1 我要走了,但我要再睡一觉sleep(10000),10s
12 17:04:48 Thread-1 走了,调用notify方法,停止对当前同一个threadSleepAndWait对象的wait阻塞,对他进行唤醒
结果解析:
1 17:04:20 Thread-0 进入了同步方法,并开始睡觉sleep,3s // Thread-0首先进入同步方法,Thread-1只能门外候着
2 17:04:23 Thread-0 sleep完成,释放掉锁,接着wait等待5s //Thread-0 sleep 1秒这段时间,Thread-1没进来,证明sleep没有释放锁
3 17:04:23 Thread-0 wait(5000)等待执行之前,这里当前执行的线程释放掉锁,所以另外一个线程就能进行进入这个方法开始执行了,同时新线程开始wait(5000) // Thread-0开始wait后Thread-1马上就进来了,证明线程的wait释放了锁
4 17:04:23 Thread-1 进入了同步方法,并开始睡觉sleep,3s //因为Thread-0开始wait了,释放锁了,所以Thread-1就拿到锁开始进入test方法
5 17:04:26 Thread-1 sleep完成,释放掉锁,接着wait等待5s //执行到sleep,Thread-1一直持有锁,
6 17:04:26 Thread-1 wait(5000)等待执行之前,这里当前执行的线程释放掉锁,所以另外一个线程就能进行进入这个方法开始执行了,同时新线程开始wait(5000) //Thread-1 并睡醒之后开始wait,Thread-1也释放了锁,
7 17:04:28 Thread-0 wait(5000)等待执行之后 //Thread-0 wait结束了,所以Thread-0开始往下走,走到下面的sleep继续睡觉
8 17:04:28 Thread-0 我要走了,但我要再睡一觉sleep(10000),10s //Thread-0开始sleep,并一直拿着锁,
9 17:04:38 Thread-0 真的走了,停止对当前同一个threadSleepAndWait对象的wait阻塞 //释放锁,并输出此行内容
10 17:04:38 Thread-1 wait(5000)等待执行之后 //此时Thread-1开始拿到锁开始下面的睡觉,到最后执行完毕
11 17:04:38 Thread-1 我要走了,但我要再睡一觉sleep(10000),10s
12 17:04:48 Thread-1 真的走了,停止对当前同一个threadSleepAndWait对象的wait阻塞
这篇关于【多线程】并发编程wait和sleep的区别的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!