LockSupport

目录

1 是什么

2 线程等待唤醒机制(wait/notify)

2.1 3种让线程等待和唤醒的方法

2.2 Object类中的wait和notify方法实现线程等待和唤醒

2.2.1 DEMO-wait/notify最原始的案例

2.2.2 如果去除synchronized的代码,注释掉以后

2.2.3 先执行notify,后执行wait是否可以?测试

2.3 Condition接口中await后signal方法实现线程的等待和唤醒

2.3.1 注释lock unlock方法

2.3.2  await和signal调换顺序

2.4 传统的synchronized和Lock方法实现线程的等待唤醒通知的约束

2.5 LockSupport类中的park等待和unpark唤醒

2.5.1 是什么

2.5.2 主要方法

2.5.3 DEMO

2.5.4 底层代码解析

2.5.6 面试题

 3 参考文献


1 是什么

2 线程等待唤醒机制(wait/notify)

2.1 3种让线程等待和唤醒的方法

1.使用Object中的wait()方法让线程等待,使用Object中的notify()方法唤醒线程

2.使用JUC保重的Condition的await方法让线程等待 ,使用signal()方法唤醒线程

3.LockSupport类可以阻塞当前线程以及唤醒指定被阻塞的线程。

2.2 Object类中的wait和notify方法实现线程等待和唤醒

2.2.1 DEMO-wait/notify最原始的案例

public class LockSupportDemo {
    static Object objectLock = new Object();

    public static void main(String[] args) {
        new Thread(() -> {
            synchronized (objectLock) {
                System.out.println(Thread.currentThread().getName() + "\t -----come in");
                try {
                    objectLock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "\t -----被唤醒");

            }
        }, "A").start();

        new Thread(() -> {
            synchronized (objectLock) {
                objectLock.notify();
                System.out.println(Thread.currentThread().getName() + "\t -----通知");
            }
        }, "B").start();
    }
}

输出

A     -----come in
B     -----通知
A     -----被唤醒

2.2.2 如果去除synchronized的代码,注释掉以后

//    synchronized (objectLock) {
        wait/notify
//}

输出:

A     -----come in
Exception in thread "A" Exception in thread "B" java.lang.IllegalMonitorStateException
    at java.lang.Object.wait(Native Method)
    at java.lang.Object.wait(Object.java:502)
    at com.demo.a18_lock.LockSupportDemo.lambda$main$0(LockSupportDemo.java:17)
    at java.lang.Thread.run(Thread.java:748)
java.lang.IllegalMonitorStateException
    at java.lang.Object.notify(Native Method)
    at com.demo.a18_lock.LockSupportDemo.lambda$main$1(LockSupportDemo.java:28)
    at java.lang.Thread.run(Thread.java:748)

wait和notify必须要在同步代码块或者方法里面且成对出现使用

2.2.3 先执行notify,后执行wait是否可以?测试

在A线程中增加睡眠

new Thread(() -> {
            try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); }
            synchronized (objectLock) {
                System.out.println(Thread.currentThread().getName() + "\t -----come in");
                try {
                    objectLock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "\t -----被唤醒");

            }
        }, "A").start();

输出

B     -----通知
A     -----come in

且程序未结束 

由于先notify,后wait,wait后没有任务唤醒线程,故被唤醒代码未执行,且程序一直处于wait状态。

故,先wait后notify才可以

2.3 Condition接口中await后signal方法实现线程的等待和唤醒

public class LockSupportDemo2 {
    static Lock lock = new ReentrantLock();
    static Condition condition = lock.newCondition();

    public static void main(String[] args) {
        new Thread(() -> {
            lock.lock();
            try {
                System.out.println(Thread.currentThread().getName() + "\t -----come in");
                try{
                    condition.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "\t -----被唤醒");
            } finally {
                lock.unlock();
            }
        }, "A").start();

        new Thread(() -> {
            lock.lock();
            try {
                condition.signal();
                System.out.println(Thread.currentThread().getName() + "\t -----通知");
            } finally {
                lock.unlock();
            }
        }, "B").start();
    }
}

输出

A     -----come in
B     -----通知
A     -----被唤醒

2.3.1 注释lock unlock方法

输出

 await和signal也要配合 lock和unlock方法使用。

2.3.2  await和signal调换顺序

输出

 和上面synchronized一样,顺序不可调整。

2.4 传统的synchronized和Lock方法实现线程的等待唤醒通知的约束

线程先要获得并持有锁,必须在锁块(synchronized或lock)中。

必须要先等待后唤醒,线程才能够被唤醒。

2.5 LockSupport类中的park等待和unpark唤醒

2.5.1 是什么

通过park()和unpark(thread)方法来实现阻塞和唤醒线程的操作。

2.5.2 主要方法

API:

阻塞:

唤醒:

2.5.3 DEMO

无所块要求:

public class LockSupportDemo3 {
    public static void main(String[] args) {
        Thread a = new Thread(() -> {
            System.out.println(Thread.currentThread().getName() + "\t -----come in");
            LockSupport.park();//被阻塞...等待通知,等待放行
            System.out.println(Thread.currentThread().getName() + "\t -----被唤醒");
        }, "a");
        a.start();

        try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); }

        Thread b = new Thread(() -> {
            LockSupport.unpark(a);//被阻塞...等待通知,等待放行
            System.out.println(Thread.currentThread().getName() + "\t -----通知");
        }, "b");
        b.start();
    }
}

改成先唤醒后等待,测试

可以看出,LockSupport没有报错,unpark可以在park之前执行, 只是park无效,没有阻塞效果,可以看到输出中时间戳一致,park形同虚设

2.5.4 底层代码解析

 

2.5.6 面试题

 3 参考文献

以上内容均来自下方的视频,仅用于个人学习笔记记录使用

Java面试_高频重点面试题 (第一、二、三季)_ 面试 第1、2、3季_柴林燕_周阳_哔哩哔哩_bilibili

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值