java wait与sleep
Youcan. 人气:01. wait() 与wait( long timeout ) 区别
public class WaitDemo4 { public static void main(String[] args) { Object lock = new Object(); Object lock2 = new Object(); new Thread(() -> { System.out.println("线程1: 开始执行" + LocalDateTime.now()); synchronized (lock) { try { lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("线程1: 执行完成" + LocalDateTime.now()); } },"无参wait线程").start(); new Thread(() -> { System.out.println("线程2: 开始执行" + LocalDateTime.now()); synchronized (lock2) { try { lock2.wait(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("线程2: 执行完成" + LocalDateTime.now()); } },"有参wait线程").start(); } } 输出: 线程2: 开始执行2022-04-12T12:13:57.130 线程1: 开始执行2022-04-12T12:13:57.130 线程2: 执行完成2022-04-12T12:13:58.130
不同点:
1.wait( long timeout) :当线程超过了设置时间之后,自动恢复执行;而wait() 无线等待状态。
2. 使用无参的wait方法,线程会进入WAITING; 使用有参的wait方法,线程会进入TIMED_WAITING。
public class WaitDemo5 { public static void main(String[] args) { Object lock = new Object(); Object lock2 = new Object(); new Thread(() -> { synchronized (lock2) { System.out.println("线程2: 开始执行" + LocalDateTime.now()); try { lock2.wait(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 (lock2) { System.out.println("唤醒线程2"); lock2.notify(); } }).start(); } } 输出: 线程2: 开始执行2022-04-12T12:28:23.200 唤醒线程2 线程2: 执行完成2022-04-12T12:28:24.169
public class WaitDemo6 { public static void main(String[] args) { Object lock = new Object(); new Thread(() -> { System.out.println("线程1: 开始执行" + LocalDateTime.now()); synchronized (lock) { try { lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("线程1: 执行完成" + LocalDateTime.now()); } },"无参wait线程").start(); new Thread(() -> { System.out.println("线程2: 开始执行" + LocalDateTime.now()); synchronized (lock) { try { lock.wait(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(); } } 输出: 线程1: 开始执行2022-04-12T12:34:34.317 线程2: 开始执行2022-04-12T12:34:34.317 唤醒所有线程 线程2: 执行完成2022-04-12T12:34:35.295 线程1: 执行完成2022-04-12T12:34:35.295
共同点:
1. 无论是有参的wait方法还是无参的wait方法,它都可以使用当前线程进入休眠状态。
2.无论是有参的wait方法还是无参的wait方法,它都可以使用notify / ontifyAll进行唤醒。
2. wait(0) 与 sleep(0)区别
public class WaitSleepDemo7 { public static void main(String[] args) { Object lock = new Object(); Thread t1 = new Thread(() -> { synchronized (lock) { System.out.println("线程1:开始执行"); try { lock.wait(0); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("线程1:执行结束"); } },"wait(0)"); t1.start(); Thread t2 = new Thread(() -> { System.out.println("线程2:开始执行"); try { Thread.sleep(0); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("线程2:执行结束"); }, "sleep(0)"); t2.start(); } } 输出: 线程1:开始执行 线程2:开始执行 线程2:执行结束
wait (0) : 无限期等待下去,相当于wait();
sleep(0) :相当于Thread.yeild() , 让出CPU执行权,重新调度,但是sleep(0) 会继续执行。
3. wait 和sleep 释放代码
wait 和 sleep 在有所的情况下的锁处理行为是完全不同的:
public class WaitSleepDemo8 { public static void main(String[] args) throws InterruptedException { Object lock = new Object(); Object lock2 = new Object(); Thread t1 = new Thread(() -> { synchronized (lock) { System.out.println("线程1:开始执行"); try { lock.wait(3 * 1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("线程1:结束执行"); } }, "wait"); t1.start(); Thread t2 = new Thread(() -> { synchronized (lock2) { System.out.println("线程2:开始执行"); try { Thread.sleep(3 * 1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("线程2:结束执行"); } }, "sleep"); t2.start(); // 创建 2 个线程,先让线程休眠 1s 之后,尝试获取,看能不能获取到锁 // 如果可以获取到锁,说明休眠时线程是释放锁的,而如果获取不到锁,说明是不释放锁 Thread t3 = new Thread(() -> { try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("尝试获取 wait 方法的锁"); synchronized (lock) { System.out.println("成功获取 wait 的锁"); } }, "wait2"); t3.start(); Thread t4 = new Thread(() -> { try { TimeUnit.SECONDS.sleep(0); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("尝试获取 sleep 方法的锁"); synchronized (lock2) { System.out.println("成功获取 sleep 的锁"); } }, "sleep2"); t4.start(); } } 输出: 线程1:开始执行 线程2:开始执行 尝试获取 sleep 方法的锁 尝试获取 wait 方法的锁 成功获取 wait 的锁 线程1:结束执行 线程2:结束执行 成功获取 sleep 的锁
wait方法(不管是有参还是无参)在执行的时候都会释放锁;而sleep 方法不会释放锁。
4. wait 与 sleep 区别
相同点:
1. 都是可以让线程进入休眠
2. 都可以响应Interrupt(中断)请求
不同点:
1. wait必须配合synchronized一起使用;而sleep不需要。
2. wait 属于Object(对象)的方法;而sleep属于Thread(线程)的方法。
3. sleep 不释放锁;而wait释放锁。
4. sleep 必须要传递一个数值类型的参数;而wait可以不传参。
5. sleep 让线程进入到TIMED_WAITING状态;而无参的wait方法让线程进入了WAITING状态。
6. 一般情况下,sleep只能等待超时时间之后再回复执行;而wait可以接受notify / notifiAll之后就绪执行。
(MS):
1.为什么 wait 释放锁⽽ sleep 不释放锁?
【JVM 强制语法检查,wait ⽅法默认等待⽆期限】
2.为什么 wait 要放在 Object 中?
【wait 使⽤要加锁,也就是要操作锁,锁是针对对象级别的⽽⾮线程级别的,线程和对象是⼀对多,所以 wait 最便利的⽅式是放在 Object 中】
加载全部内容