zoukankan      html  css  js  c++  java
  • 线程通信

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

  • 相关阅读:
    DirectX9:基础篇 第六章 颜色
    DirectX9:应用篇 论OBJ模型文件格式
    MFC:绘图基础
    DirectX9:基础篇 纹理
    DirectX9:应用篇 论OBJ模型文件和.X模型文件互转
    MFC:控件位置调整
    数据结构:二叉树
    DirectX9:总结篇 数据类型结构
    C89:论结构体/枚举体/联合体的使用
    css布局汇总
  • 原文地址:https://www.cnblogs.com/Myarticles/p/12046038.html
Copyright © 2011-2022 走看看