(多线程)wait & notify

目录

🌍使用(观察执行顺序)

🚩wait()不带参数的api

🚩运行结果

🚩完整的执行逻辑

🚩wait(time)带参数的api

🚩运行结果

🚩空打一炮问题

🌍wait和sleep的对比


       我们知道了,线程具有随机调度的特点,但是有时候我们确实需要控制线程的执行顺序。目前我们知道 join 可以控制执行顺序。但是通过 join 会直接使一个线程直接阻塞,并不是我们想要的效果。我们需要的是将线程的某段逻辑阻塞等待。所谓我们需要使用 wait 。使用wait需要和 notify搭配使用。

使用(观察执行顺序)

一个wait对应一个notify,并别都需要搭配锁(synchronized)使用。

wait()不带参数的api

public class Demo1 {
    public static void main(String[] args) throws InterruptedException {
        Object clock = new Object();
        Thread t1 = new Thread(()->{
           while (true){
               synchronized (clock){
                   try {
                       System.out.println("wait 开始");
                       clock.wait();
                       System.out.println("wait 结束");
                   } catch (InterruptedException e) {
                       e.printStackTrace();
                   }
               }
           }
        });
        t1.start();
        Thread.sleep(1000);
        Thread t2 = new Thread(()->{
                synchronized (clock){
                    System.out.println("notify 开始");
                    clock.notify();
                    System.out.println("notify 结束");
            }
        });
        t2.start();
    }
}

通过结果的打印顺序,我们来看wait 和notify的相互搭配使用。

运行结果

完整的执行逻辑

       可以看到,t1线程里有while循环,t2线程没有,我们让t1线程先执行了一秒,但是我们看到打印了wait开始只有并没有紧接着打印wait结束,原因就是我们调用了clock.wait,于是解锁,阻塞等待t2线程,当t2线程 打印了notify开始,执行了clock.notify,我们t1线程的wait阻塞才被解开,但是由于notify也占用着锁t1 线程获取不到锁,不能接着往下执行打印wait结束语句,等t2线程执行了打印notify结束,释放了锁,t1线程才能重新拿到锁然后接着往下执行打印wait结束语句,此时t2线程没有循环,也就是线程执行结束了,但是t1线程的逻辑处在while死循环里又打印了wait开始和clock.wait语句,但是等不到notify就出现了上面的打印结果。整个main线程也结束不了

wait(time)带参数的api

参数表是当前wait的最大阻塞等待时间,如果超时了,线程就会继续往下执行。

public class Demo1 {
    public static void main(String[] args) throws InterruptedException {
        Object clock = new Object();
        Thread t1 = new Thread(()->{
               synchronized (clock){
                   try {
                       System.out.println("wait 开始");
                       clock.wait(2000);
                       System.out.println("wait 结束");
                   } catch (InterruptedException e) {
                       e.printStackTrace();
                   }
               }
        });
        t1.start();
        Thread.sleep(4000);
        Thread t2 = new Thread(()->{
                synchronized (clock){
                    System.out.println("notify 开始");
                    clock.notify();
                    System.out.println("notify 结束");
            }
        });
        t2.start();
    }
}

运行结果

       我们设置了wait的最大等待时间为两秒,但是我们的notify在t2线程,而t2线程我们设置了sleep(4000),才能开始执行,明显超过了wait的最大等待时间,而从结果上来看,也确实跟我们的预期一样。

空打一炮问题

        虽然我们的main线程也是正常退出了,但是实际上我们的notify的使用上出现了问题,wait和notify是互相搭配使用的,是wait阻塞了,收到了notify解锁的通知接着执行,但是上述代码中我们的notify实际上并没有解锁(wait的阻塞),因为在之前wait就执行结束了,这就造成了空打一炮的结果。虽然并没有对我们的程序造成什么影响,但是这样的使用是错误的。

wait和sleep的对比

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值