Java并发编程—监视器锁对象的方法

本文介绍了Java中监视器锁对象的关键方法,包括wait()、notify()和notifyAll()。wait()方法会导致线程释放锁并进入等待状态,可通过其他线程的notify()或notifyAll()唤醒,或者超时后返回。notify()和notifyAll()则用于唤醒等待的线程,前者唤醒一个,后者唤醒所有。调用这些方法时,线程必须持有锁,否则将抛出异常。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

监视器锁对象中的常用方法

1 wait()

1 该方法的是释放代用该方法的监视器锁同时该线程在此处被阻塞

2 阻塞后被唤醒的方式:

(1)其他线程中调用了该共享对象的notify()或者notifyAll()方法;

(2)其他线程调用了该线程的interrupt()方法,抛出InterruptException异常后返回

3 注意若线程持有多个监视器锁,只会释放调用了wait()方法的监视器锁对象

public class WaitTest01 {
    public static Object resourceA = new Object();
    public static Object resourceB = new Object();

    public static void main(String[] args) {
        Thread threadA = new Thread(() -> {
            try {
                //获取A的锁
                synchronized (resourceA) {
                    System.out.println("线程A获取到A资源的锁");
                    //获取B的锁
                    synchronized (resourceB) {
                        System.out.println("线程A获取到了B资源的锁");
                        //释放A锁
                        System.out.println("线程A释放了资源A的锁");
                        resourceA.wait();//线程A是放过了A资源锁,在此处阻塞,但并未释放B资源的锁,故线程B拿不到B资源锁
                        System.out.println("线程A阻塞");
                    }
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        Thread threadB = new Thread(() -> {
            try {
                Thread.sleep(1000);
                //获取A的锁
                synchronized (resourceA) {
                    System.out.println("线程B获取到A资源的锁");
                    System.out.println("线程B尝试获取资源B锁.....");
                    //获取B的锁
                    synchronized (resourceB) {
                        System.out.println("线程B获取到了线程B的锁");
                        //释放A锁
                        System.out.println("线程B释放了资源A的锁");
                        resourceA.wait();
                    }
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        threadA.start();
        threadB.start();
        System.out.println("main over");
    }
}

最终输出结果:

main over
线程A获取到A资源的锁
线程A获取到了B资源的锁
线程A释放了资源A的锁
线程B获取到A资源的锁
线程B尝试获取资源B.....

补充:

1 wait(long timeout):线程调用该方法被挂起后,若在指定时限内未被唤醒回自己返回(wait()方法底层就是wait(0))

2 wait(long timeout, int nanos):底层调用的是wait(long timeout)

2 notify()/notifyAll

1 会唤醒调用该方法的共享对象中因调用该共享对象wait()方法而被挂起的一个线程

2 会唤醒调用该方法的共享对象中因调用该共享对象wait()方法而被挂起的所有线程

public class NotifyTest {
    public static Object obj = new Object();

    public static void main(String[] args) {
        //创建线程A
        Thread threadA = new Thread(() -> {
            synchronized (obj) {
                System.out.println("A线程执行了");
                try {
                    obj.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("A线程被唤醒了");
            }
        });
        //创建线程B
        Thread threadB = new Thread(() -> {
            synchronized (obj) {
                try {
                    System.out.println("B线程执行了");
                    obj.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("B线程被唤醒了");
            }
        });

        //创建线程C用来唤醒线程
        Thread threadC = new Thread(() -> {
            synchronized (obj) {
                System.out.println("线程C执行了");
                obj.notify();
                //obj.notifyAll();
            }
        });

        //启动A和B
        threadA.start();
        threadB.start();

        //唤醒其中的一个线程
        try {
            Thread.sleep(1000);
            threadC.start();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        //等待两个线程结束
        try {
            threadA.join();
            threadB.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("main over");
    }
}
3 注意事项

注意这些方法都是说共享对象的方法,就是说该线程必须持有该共享对象才能调用该方法,否则会抛出IllegalMonitorStateException异常

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值