• 线程通信


    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()也是需要使用锁的。

  • 相关阅读:
    SpringBoot RequestBody ajax提交对象
    微信小程序常用样式汇总
    微信小程序常用控件汇总
    java多线程实现多客户端socket通信
    客户端连接Codis集群
    crontab 解析
    在 RHEL/CentOS 7 上配置NTP时间服务器
    tomcat的bin目录中startup.bat/tomcat.6.exe/tomcat6w.exe区别
    Windows 下tomcat安装及将多个tomcat注册为Windows服务
    Oracle 数据库排错之 ORA-00600
  • 原文地址:https://www.cnblogs.com/Myarticles/p/12046038.html
Copyright © 2020-2023  润新知