【线程】——等待集(wait,notify,notifyAll)

对象中的等待集(wait,notify,notifyAll)

  • 我们知道线程是的操作是抢占式执行的,我们假想有多个线程在等待一个cpu给提供资源,但是其中线程x抢cpu抢的快,但是当前cpu并没有那个可以给x提供的资源,又因为这个x不停的抢cpu,导致其他线程不能进入到cpu中,因此会影响到程序的运行效率。

为了解决这个问题,我们引入了对象等待集,也就是wait,notify,notifyAll三个关键字,要和synchronized一起用

  • wait 如果cpu中没有满足这个线程执行的资源时候,让这个线程等待,wait()会使线程状态发生变化(runnable–>waiting,waiting–>runnable)
  • 等的是对像的等待集上(wait()是Object的一个方法,所以等在该对象的等待集上)
  • 使用的时候必须加锁,等在哪个对象上,就对哪个对象加锁(wait()执行成功时会释放锁,醒来时会重新请求锁)
  • notify 当cpu中的条件成熟的时候,通知指定的线程工作,唤醒一个线程
  • notifyAll 是一个唤醒所有线程,让这些线程去竞争一把锁
  • 哪个线程调用wait(),哪个线程进入等待集

举例分析
在这里插入图片描述
那么这种情况如何解决呢?
那就是该线程发现条件还没有成熟(也就是发现ATM机没钱的时候),就应该释放锁,并且等待,知道其他线程通知说条件已经成熟了,然后把该线程唤醒(也就是运钞扯来了,并且把钱放进ATM机了,或者是后面的人进去存钱,存好了之后跟他说我刚刚存钱了,你可以进去取钱了)
关键在于需要根据实际情况来手动控制线程之间的先后顺序。(虽然线程的执行顺序是由调度器实现的,但是有时候要控制先后顺序的hi后就需要手动实现)——这就引出了等待集

等待集的核心操作主要有两个
1.等待(wait方法)
2.通知(notify方法)

在这里插入图片描述

notify用法

import java.util.Scanner;

public class ThreadDemo12 {
    private static Object object = new Object();
    public static class MyThread extends  Thread{
        @Override
        public void run() {
            synchronized (object){
                try {
                    object.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            for (int i = 10; i < 20; i++) {
                System.out.println(i);
            }
        }
    }
    public static void main(String[] args){
        Thread thread = new MyThread();
        thread.start();
        Scanner scanner = new Scanner(System.in);
        System.out.println("我不输入,Thread线程就不会运行");
        scanner.nextInt();
        synchronized (object){
            object.notify();
        }
    }
}

注意
调用wait的前提是发现当前操作的条件不满足,要想知道条件满不满足,就需要先能够访问到资源(先获取到锁)
wait必须在同步代码块中才能使用,否则就会出现异常

wait方式做了三件事:
1.先释放锁(前提是已经获取到锁)
2.等待通知(等待其他线程调用notify方法,把它唤醒)
3.收到通知后会重新尝试获取锁
在这里插入图片描述

从内核角度分析
在这里插入图片描述

竞态条件问题:

wait:
1.释放锁
2.等待通知
3.获取锁
因为wait的前两步都是原子性操作,所有wait不存在竞态条件问题
在这里插入图片描述

wait 和 sleep 的对比

理论上:wait 和 sleep 是没有可比性的,wait()用于线程之间的通信的,sleep()使线程阻塞一段时间。

相同点:都可以让线程放弃执行一段时间。

  1. wait 之前需要请求锁,而wait执行时会先释放锁,等被唤醒时再重新请求锁。这个锁是 wait 对像上的 monitor
    lock
  2. sleep 是无视锁的存在的,即之前请求的锁不会释放,没有锁也不会请求。
  3. wait 是 Object 的方法
  4. sleep 是 Thread 的静态方法
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值