1. 所有对象都会有一个wait set,用于存放调用了该对象wait方法之后进入block状态的线程;
2. 线程被notify之后,不一定会立即执行;
3. 线程从wait set中唤醒的顺序不一定是FIFO;
4. 线程被唤醒后,必须重新获取锁。
public class WaitSet { private final static Object lock = new Object(); /** * 1. 所有对象都会有一个wait set,用于存放调用了该对象wait方法之后进入block状态的线程 * 2. 线程被notify之后,不一定会立即执行 * 3. 线程从wait set中唤醒的顺序不一定是FIFO * @param args * @throws InterruptedException */
    public static void main(String[] args) throws InterruptedException { IntStream.rangeClosed(1, 10).forEach(i->{ new Thread(String.valueOf(i)){ @Override public void run() { synchronized (lock){ try { System.out.println(Thread.currentThread().getName() + " will come to wait"); lock.wait(); System.out.println(Thread.currentThread().getName() + " will leave to wait"); } catch (InterruptedException e) { e.printStackTrace(); } } } }.start(); }); // 让主线程暂停3秒,让所有的线程进入等待状态,再逐个进行唤醒
        TimeUnit.SECONDS.sleep(3); // 逐个唤醒线程
        IntStream.rangeClosed(1, 10).forEach(i->{ synchronized (lock){ lock.notify(); try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } } }); } }

 

输出结果:

SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。

多线程的休息室WaitSet详细介绍 随笔 第1张

 

二、线程notify之后的操作

wait执行完,被其他线程唤醒的时候,需要再次去抢锁,且在其wait的时候会记录此时的地址,下次被唤醒抢到锁资源的时候就执行从记录的地址出向下执行。

 

测试代码如下:

public class WaitSet { private final static Object lock = new Object(); private static void work(){ synchronized (lock){ System.out.println("begin..."); try { System.out.println("thread is coming..."); lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("thread will leave..."); } } public static void main(String[] args) throws InterruptedException { new Thread(()->{ work(); }).start(); TimeUnit.SECONDS.sleep(2); synchronized (lock){ lock.notify(); } } }

 

 输出结果:

多线程的休息室WaitSet详细介绍 随笔 第2张

 

 

 

 

ni

扫码关注我们
微信号:SRE实战
拒绝背锅 运筹帷幄