• 线程通信


    wait()与notify()

    首先考虑下面的情景,一个线程必须要等另外一个线程执行完才能继续执行,可以设置一个变量,第二个线程一直监控它,当第一个线程执行完后修改这个变量的值,第二个线程监控到值发生了改变然后继续执行,如下代码

    public class Demo {
        private volatile boolean signal = false;
    
        public static void main(String[] args) {
            Demo d = new Demo();
    
            // 第一个线程
            new Thread(() -> {
                System.out.println("准备数据。。。。。");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                d.signal = true;
            }).start();
            // 第二个线程
            new Thread(() -> {
                while (!d.signal) {
                    // 这里防止一直循环 稍微休眠
                    try {
                        Thread.sleep(800);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println("模拟代码执行。。。。");
            }).start();
        }
    }
    

    上面的方式通过while循环去阻塞,会非常的耗费资源,那么有没有更简单的方式呢?答案是有的

    在Object对象中,有两个方法,wait()跟notify(),它们的作用就是用来阻塞线程跟唤醒线程

    首先需要了解使用它们的条件:

    • 在同步代码块中使用
    • 使用的必须是同步代码块对象的wait()与notify()方法
    public class Demo {
        public static void main(String[] args) {
            Demo d = new Demo();
    
            // 第一个线程
            new Thread(() -> {
                System.out.println("准备数据。。。。。");
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("准备数据完成。。。");
                synchronized (d) {
                    d.notify();
                }
            }).start();
    
            for (int i = 0; i < 2; i++) {
                new Thread(() -> {
                    System.out.println(Thread.currentThread() + "等待代码执行。。。");
                    synchronized (d) {
                        try {
                            d.wait();   // wait会释放锁
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println(Thread.currentThread() + "模拟代码执行。。。。");
                }).start();
            }
        }
    }
    

    关于wait与notify的特点

    • wait()在执行后会释放掉synchronized锁,因此使得上面的代码执行起来没有问题
    • 执行notify()方法会加锁
    • notify()只会随机唤醒一个被等待的线程,如果需要全部唤醒,则必须执行notifyAll()方法

    Condition条件锁

    Condition接口中的await()跟signal()方法的作用与wait()跟notify()的一致

    Condition使用实例:

    public class ConditionTest {
        private Lock lock = new ReentrantLock();
        private Condition a = lock.newCondition();
        private Condition b = lock.newCondition();
    
        public void a() {
            while (true) {
                lock.lock();
                try {
                    a.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("a");
                b.signal();
                lock.unlock();
            }
        }
    
        public void b() {
            while (true) {
                lock.lock();
                a.signal();
                System.out.println("b");
                try {
                    b.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                lock.unlock();
            }
        }
    
        public static void main(String[] args) {
            ConditionTest ct = new ConditionTest();
            // 要求:a b c方法有序执行
            new Thread(ct::a).start();
    
            new Thread(ct::b).start();
        }
    }
    

    通过上面的实例,可以知道await()跟signal()也是需要使用锁的。

  • 相关阅读:
    阿里P8推荐的SpingBoot学习手册+Git开源项目实践分享,还不收藏
    阿里P8划重点:JVM+Spring+Mybatis+多线程高并发源码你必须会
    一线大厂工程师推荐:Mysql、Springboot、JVM、Spring等面试合集
    GitHub标星120K+的JDK并发编程指南,连续霸榜GitHub终于开源了
    腾讯被指劝退高龄员工,华为百度也在优化,互联网35岁+该怎么办
    天猫面试官硬核推荐:Dubbo+ES+JVM+多线程/高并发+消息队列
    多线程与高并发:金九银十跳槽季面试必须要掌握的硬核涨薪技能
    纯干货,源码6步曲,带你解析完整的ThreadPoolExecutor
    今日总结
    今日头条技术架构分析
  • 原文地址:https://www.cnblogs.com/Myarticles/p/12046038.html
Copyright © 2020-2023  润新知