Java多线程 wait() 和 notify() 还有notifyAll() 使用前提和作用以及判断唤醒哪些线程的本质总结

Object有关于多线程的默认方法,它们的作用如下:
wait() : 使得调用的此方法的线程等待
notify() : 唤醒一个等待中的线程(通常是最先等待的线程)
notifyAll():唤醒所有等待中的线程(倒序唤醒,即最近wait()最先被唤醒)

使用前提
上面三个方法,使用之前必须获得锁,即必须在synchronized方法里面或者
synchronized代码块中使用,如:

public class A {
    synchronized public void backupA() {
        try {
            System.out.println("A wait");
            wait();
            System.out.println("A run");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

我们可以看到 wait()其实可以写成this.wait(),说明是该类的实例对象调用此方法,
而synchronized方法使用的锁对象也是this,即该类的实例对象
说明wait()不止得在同步方法或同步块中使用,还必须是锁对象来调用此方法,
notify()和notifyAll()也一样

我们可以把代码改成

public class A {
    private Object object = new Object();
    synchronized public void backupA() {
        try {
            System.out.println("A wait");
            object.wait();
            System.out.println("A run");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

可以看出调用wait()的对象,不是锁对象,在重写的run()方法中调用此方法
会出现java.lang.IllegalMonitorStateException异常,就是因为使用wait()方法的对象
并没有获得监视器,即没有获得锁

唤醒线程是唤醒哪些线程呢,任意等待线程吗
结论:锁对象调用notify()和notifyAll()方法只能唤醒该锁对象调用wait()的线程,简单来说就是如果有两个锁对象,一个锁对象运行wait()使得该线程等待,另外一个锁对象运行
唤醒方法notify()将无法唤醒

例子如下,有5个类
A.class
B.class
ThreadA.class
ThreadB.class
Test.class

A.class

public class A {
    synchronized public void backupA() {
        try {
            System.out.println("A wait");
            this.wait();
            System.out.println("A run");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

B.class

public class B {
    synchronized public void backupB() {
        System.out.println("B notify");
        this.notify();
        System.out.println("B run");
    }
}

ThreadA.class

public class ThreadA extends Thread {
    private A a;
    public ThreadA(A a) {
        this.a = a;
    }
    @Override
    public void run() {
        a.backupA();
    }
}

ThreadB.class

public class ThreadB extends Thread {
    private B b;
    public ThreadB(B b) {
        this.b = b;
    }
    @Override
    public void run() {
        b.backupB();
    }
}

Test.class

public class Test {
    public static void main(String[] args) throws InterruptedException {
        A a = new A();
        B b = new B();
        ThreadA threadA = new ThreadA(a);
        ThreadB threadB = new ThreadB(b);
        threadA.start();
        Thread.sleep(500);
        threadB.start();
    }
}

结果
请添加图片描述
可以看出B类中运行的notify() 无法唤醒A类中运行wait()方法后等待的线程,
因为B类中使用B的实例对象作为锁,A类中使用A的实例对象作为锁,两者锁不同,
则使用wait()和notify()的对象不同,无法唤醒

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lolxxs

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值