等待和通知机制(wait和notify)

2023-10-29

1. 等待和通知机制的实现
wait() 方法

wait() 是 Object 类的方法,它的作用是使当前执行wait方法的线程进行等待,该方法将当前线程置入“预执行队列”中,并在 wait() 所在的代码行处停止执行,直到接到通知或者被中断才能继续执行。线程必须获得该对象的对象锁,即只能在同步方法或者同步方法块中调用 wait() 方法,在执行 wait() 方法后,当前线程释放所拥有的对象锁,如果 wait() 没有持有对象锁就执行,会抛出 IllegalMonitorStateException 异常

notify() 方法

notify() 是 Object 类的方法,作用是使停止的线程继续运行,也要在同步方法或者同步块中调用。该方法用来通知那些可能等待该对象的对象锁的其他线程,如果有多个线程等待,则由线程规划器随机挑选处一个呈 wait 状态的线程,对其发出通知 notify,但是被通知的线程不会马上执行 wait 后面的代码,因为使用 notify 的线程不会马上释放锁,所以被通知的线程也不会马上得到锁。如果调用 notify 时没有持有对象锁,就会抛出 IllegalMonitorStateException 异常

使用 wait() 和 notify() 方法进行测试

class MyThread1 extends Thread {

    private Object lock;

    public MyThread1(Object lock) {
        this.lock = lock;
    }

    @Override
    public void run() {
        synchronized (lock) {
            System.out.println(Thread.currentThread().getName()
                    + " 开始 wait time = " + System.currentTimeMillis());
            try {
                //wait 使线程 thread1 停止运行
                lock.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()
                    + " 结束 wait time = " + System.currentTimeMillis());
        }
    }
}

class MyThread2 extends Thread {

    private Object lock;

    public MyThread2(Object lock) {
        this.lock = lock;
    }

    @Override
    public void run() {
        synchronized (lock) {
            System.out.println(Thread.currentThread().getName()
                    + " 开始 notify time = " + System.currentTimeMillis());
            //线程 thread2 使停止的 thread1 继续运行
            lock.notify();
            System.out.println(Thread.currentThread().getName()
                    + " 结束 notify time = " + System.currentTimeMillis());
        }
    }
    
}

public class Test extends Thread {
    public static void main(String[] args) throws InterruptedException {
        Object lock = new Object();
        MyThread1 thread1 = new MyThread1(lock);
        thread1.start();
        Thread.sleep(2000);
        MyThread2 thread2 = new MyThread2(lock);
        thread2.start();
    }
    
}

结果是:

AAA 开始 wait time = 1540528981658
BBB 开始 notify time = 1540528983660
BBB 结束 notify time = 1540528983661
AAA 结束 wait time = 1540528983661

简单分析一下整个过程,线程 AAA 先执行 run() 方法,获得了 lock 对象锁,输出一行之后执行 lock.wait() 方法,表示线程 AAA 释放对象 lock,然后持有该对象锁的线程 AAA 进入等待状态,但是线程 AAA 依然在 synchronized 同步块中;
由于线程 AAA 停止了,此时线程 BBB 开始执行 run() 方法,获取 lock 对象锁,输出一行之后,调用 lock.notify() 唤醒正在等待对象锁 lock 的线程 AAA,使其进入就绪状态,但线程 BBB 并不马上释放对象锁 lock,而是继续执行自己同步方法中的剩余方法。只有当线程 BBB 执行完 syncrhonized 同步块之后,才释放对象锁,此时被唤醒的线程 AAA 才可以重新获得该对象锁,然后执行 wait() 方法之后的代码

整个过程如图所示,简单来说,就是线程 AAA 被 wait,然后线程 BBB 使用 notify 唤醒线程 AAA,但是不立即释放锁,直到线程 BBB 执行完同步块之后,才释放锁,此时线程 AAA 得到锁,开始执行 wait 后的方法

有一点需要注意,wait() 方法是使 拥有对象锁的那个线程暂时等待,而与谁是那个对象锁没有关系,就像这个例子中,线程 AAA 拥有 Object 对象的对象锁 lock,同时在 run() 方法中用对象锁 lock 调用 wait() 方法,然后对象锁 lock 被释放,注意,是线程 AAA 持有的对象锁 lock被释放,因为线程 AAA 在同步块中,随即造成的是,线程 AAA 进入等待状态。这一点很重要!!!

同时,在同步代码块中,必须调用获取的锁对象的 wait、nofity 或者 notifyAll 方法,在等待线程中,调用 wait() 方法的那个对象一定是 synchronized() 括号里的那个对象,而在通知线程中,调用 notify() 方法的那个对象也一定是 synchronized 括号里的那个对象,如果不是的话,会抛出 IllegalMonitorStateException 异常

notify()只能唤醒一个线程

如果有多个线程处于等待状态,那么 notify() 方法只能随机唤醒一个线程,其他没有没唤醒的线程依旧处于等待状态。但是可以多次调用 notity() 方法来随机唤醒多个线程

//Service2 方法
class Service2 {

    public void testMethod(Object lock) {

        synchronized (lock) {
            System.out.println(Thread.currentThread().getName()
                    + " beg1in wait " + System.currentTimeMillis());
            try {
                lock.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()
                    + " end wait " + System.currentTimeMillis());
        }

    }

}

创建三个线程 ThreadA6、ThreadB6 和 ThreadC6

class ThreadA6 extends Thread {

    private Object lock;

    public ThreadA6(Object lock) {
        this.lock = lock;
    }

    @Override
    public void run() {
        Service2 service2 = new Service2();
        service2.testMethod(lock);
    }

}

class ThreadB6 extends Thread {

    private Object lock;

    public ThreadB6(Object lock) {
        this.lock = lock;
    }

    @Override
    public void run() {
        Service2 service2 = new Service2();
        service2.testMethod(lock);
    }

}

class ThreadC6 extends Thread {

    private Object lock;

    public ThreadC6(Object lock) {
        this.lock = lock;
    }

    @Override
    public void run() {
        Service2 service2 = new Service2();
        service2.testMethod(lock);
    }
}

随机唤醒一个正在等待的线程的方法

class NotifyOne extends Thread {

    private Object lock;

    public NotifyOne(Object lock) {
        this.lock = lock;
    }

    @Override
    public void run() {
        synchronized (lock) {
            System.out.println("NotifyOne");
            lock.notify();
        }
    }
}

多次调用可以随机唤醒多个正在等待的线程的方法

class NotifyMulti extends Thread {

    private Object lock;

    public NotifyMulti(Object lock) {
        this.lock = lock;
    }

    @Override
    public void run() {
        synchronized (lock) {
            System.out.println("NotifyMulti");
            lock.notify();
            lock.notify();
            lock.notify();
            lock.notify();
            lock.notify();
        }
    }
}

测试方法

public class Test2 {

    public static void main(String[] args) throws InterruptedException {
        Object lock = new Object();
        ThreadA6 threadA6 = new ThreadA6(lock);
        threadA6.start();
        ThreadB6 threadB6 = new ThreadB6(lock);
        threadB6.start();
        ThreadC6 threadC6 = new ThreadC6(lock);
        threadC6.start();

        Thread.sleep(2000);

        NotifyOne notifyOne = new NotifyOne(lock);
        notifyOne.start();
       	/*NotifyMulti notifyMulti = new NotifyMulti(lock);
        notifyMulti.start();*/
    }

}

结果是:

Thread-0 beg1in wait 1540536524678
Thread-1 beg1in wait 1540536524679
Thread-2 beg1in wait 1540536524679
notifyOne 唤醒了一个线程 1540536526679
Thread-0 end wait 1540536526679

由于只能唤醒一个线程,另外两个还处于等待状态的线程因为没有被唤醒,就处于永远等待的状态了,如果调用后面被注释的语句,那么就能唤醒多个线程了

Thread-0 beg1in wait 1540536666626
Thread-2 beg1in wait 1540536666626
Thread-1 beg1in wait 1540536666626
NotifyMulti
Thread-0 end wait 1540536668627
Thread-1 end wait 1540536668627
Thread-2 end wait 1540536668627

notifyAll()可以唤醒多个线程

由于不知道有多少个线程处于等待的状态,我们也不可能一直不停调用 notify() 方法,这样会很麻烦,因此可以使用 notifyAll() 方法唤醒全部正在等待的方法

2. 当interrupt方法遇到wait方法

当线程呈 wait() 状态时,调用线程对象的 interrupt() 方法会出现 InterruptedException 异常

class Service5 {

    public void testMethod(Object lock) {
        synchronized (lock) {
            System.out.println(Thread.currentThread().getName() + " be1gin wait "
                + System.currentTimeMillis());
            try {
                lock.wait();
                System.out.println(Thread.currentThread().getName() + " end wait "
                        + System.currentTimeMillis());
            } catch (InterruptedException e) {
                System.out.println("发生异常...");
                e.printStackTrace();
            }
        }
    }

    public void testMethod2(Object lock) {
        synchronized (lock) {
            System.out.println(Thread.currentThread().getName() + " begin 2");
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + " end 2");
        }
    }

}

class ThreadB5 extends Thread {

    private Object lock;

    public ThreadB5(Object lock) {
        this.lock = lock;
    }

    @Override
    public void run() {
        Service5 service5 = new Service5();
        service5.testMethod2(lock);
    }
}

public class ThreadA5 extends Thread {

    private Object lock;

    public ThreadA5(Object lock) {
        this.lock = lock;
    }

    @Override
    public void run() {
        Service5 service5 = new Service5();
        service5.testMethod(lock);
    }

    public static void main(String[] args) throws InterruptedException {
        Object lock = new Object();
        ThreadA5 threadA5 = new ThreadA5(lock);
        threadA5.start();
        threadA5.interrupt();
        Thread.sleep(2000);

        ThreadB5 threadB5 = new ThreadB5(lock);
        threadB5.start();
    }
}

结果是:

Thread-0 be1gin wait 1540534325308
发生异常...
java.lang.InterruptedException
	at java.lang.Object.wait(Native Method)
	at java.lang.Object.wait(Object.java:502)
	at edu.just.Service5.testMethod(ThreadA5.java:10)
	at edu.just.ThreadA5.run(ThreadA5.java:60)
Thread-1 begin 2
Thread-1 end 2

可以看到,报错了,同时还执行了 wait() 方法之后的代码,这是因为:在执行同步代码块的过程中,遇到异常而导致线程终止,锁也会被释放,此时如果还有线程持有对象锁,那么 wait 后面的代码将不会执行,而是直接报错

3. 通知时间
wait(long)方法

如果 wait() 方法里面带有参数,表示在一段时间内,如果没有其他线程对等待的线程进行唤醒,那么等待的线程在超过这个时间之后会自动唤醒

  1. 如果在规定时间之内就被唤醒,那么会先执行其他线程的代码,然后在执行 wait 之后的代码
  2. 如果在规定直接之外被唤醒,那么就会先执行 wait 之后代码,在执行其他线程的代码
public class MyRunnable {

    private static Object lock = new Object();

    private static Runnable runnable = new Runnable() {
        @Override
        public void run() {
            synchronized (lock) {

                System.out.println(Thread.currentThread().getName()
                        + " wait begin time " + System.currentTimeMillis());
                try {
                    //规定 1s 之后线程自动被唤醒
                    lock.wait(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()
                        + " wait end time " + System.currentTimeMillis());
            }
        }
    };

    private static Runnable runnable1 = new Runnable() {
        @Override
        public void run() {
            synchronized (lock) {

                System.out.println(Thread.currentThread().getName()
                        + " wait begin time2 " + System.currentTimeMillis());
                try {
                    lock.wait(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()
                        + " wait end time " + System.currentTimeMillis());
            }
        }
    };

    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(runnable);
        thread.setName("AAA");
        thread.start();
		//在规定时间之内线程 AAA 被唤醒		语句1
        Thread.sleep(1100);
		//在规定时间之外线程 AAA 被唤醒     语句2
//        Thread.sleep(900);
        Thread thread2 = new Thread(runnable1);
        thread2.setName("BBB");
        thread2.start();
    }

}

先把语句2注释掉,结果是:

AAA wait begin time 1540538435802
AAA wait end time 1540538436802
BBB wait begin time2 1540538436902
BBB wait end time 1540538436903

看到此时线程 AAA 在被线程 BBB 手动唤醒之前就自动唤醒,所以直接执行了 wait 后面的方法

在执行语句2,把语句1注释,结果是:

AAA wait begin time 1540538528885
BBB wait begin time2 1540538529784
BBB wait end time 1540538529784
AAA wait end time 1540538529885

此时线程 BBB 在线程 AAA 被自动唤醒前就将线程 AAA 唤醒了,此时先执行完线程 BBB 的代码,在执行线程 AAA wait() 方法后面的代码

4.wait()和sleep()方法的区别

wait() 方法和 sleep() 方法很类似,下面可以做个对比:

  1. wait 是 Object 类的成员变量,而 sleep 是 Thread 类的静态方法
  2. 调用 wait 方法前需要先获取对象锁,而调用 sleep 方法不需要先获取对象锁
  3. 调用 wait 方法的线程需要用 notify 来唤醒,而 sleep 方法必须设置超时值
  4. 线程调用 wait 方法后会先释放锁,而 sleep 方法不会释放锁

5.参考

《Java多线程编程核心技术》
https://mp.weixin.qq.com/s?__biz=MzIxNTQ3NDMzMw==&mid=2247483803&idx=1&sn=d40db47a68287ea10c838d5f2f9a700c&scene=19#wechat_redirect

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

等待和通知机制(wait和notify) 的相关文章

  • 从 crontab 运行 python 脚本

    我有一个通过 crontab 运行的 python 程序 并且运行良好 然而 我决定添加通知我它正在做什么的功能 但它突然失败了 它从命令行运行 但是 将其作为 crontab 程序运行会导致它失败 libnotify Message Un
  • 等待几秒钟而不阻止 UI 执行

    我想在两条指令之间等待几秒钟 但不阻止执行 例如 Thread Sleep 2000 这不好 因为它会阻塞执行 我的想法是 我调用一个方法 然后等待 X 秒 例如 20 秒 监听即将到来的事件 在 20 秒结束时 我应该根据 20 秒内发生
  • Java 每 0.5 秒在动画中移动 jlabel

    我想要简单的动画每 0 5 秒设置一次位置 但它不会仅在循环结束时设置位置动画 int x 1 整数y 1 while x lt 100 jLabel1 setLocation x y x x 10 y y 10 try Thread sl
  • Python - 等待没有高CPU使用率的条件

    在这种情况下 假设我想等待一个可能在任何随机时间发生的条件发生 while True if condition Do Whatever else pass 正如您所看到的 直到条件为 True 时才会发生 pass 但是 虽然条件不成立 但
  • html2canvas 等待图像加载

    我遇到这个问题已经有一段时间了 但我似乎找不到解决方案 我正在使用最新的 html2canvas js 插件来截取使用 fllotcharts 制作的图表的屏幕截图 然后通过隐藏输入提交 base64 屏幕截图 问题是带有图表的 div 也
  • driver.manage.wait(long timeout) 和显式等待之间的区别

    谁能说出以下的区别 driver manage wait long timeout and WebDriverWait wait new WebDriverWait driver WAIT IN SECONDS 明确等待 了解我未来的参考
  • wait 命令不会等待子进程完成 c cpp c++

    我正在尝试编写一个 C 程序 该程序创建一个子进程 运行一个命令并将输出通过管道返回到父进程正在运行的命令的输入 我让父级执行 wait NULL 或 wait void pid 命令 但它不等待 这是代码 include
  • 如何收到进入挂起模式的通知?

    我希望当系统即将挂起或睡眠 之前 时通知我的应用程序 无论是否获取唤醒锁 我不想禁止该过程 而只想收到通知 谢谢 L None
  • python 中的异步等待/非阻塞等待

    我喜欢在等待一段时间后输出字符串的每个字母 以获得打字机效果 for char in string libtcod console print 0 3 3 char time sleep 50 但这会阻塞主线程 并且程序会变为非活动状态 在
  • 如何等待按键?

    如何让我的 python 脚本等待用户按下任意键 In Python 3 use input input Press Enter to continue In Python 2 use raw input raw input Press E
  • 如何让程序等待 JavaScript 中的变量更改?

    我想强制 JavaScript 程序在执行的某些特定点等待 直到变量发生更改 有办法做到吗 我已经找到了一个名为 narrative JavaScript 的扩展 它强制程序等待事件发生 有没有办法创建一个新事件 例如 变量更改事件 其行为
  • Perl后台进程

    我正在尝试在 perl 中运行后台进程 我创建了一个子进程 用于调用另一个 perl 脚本 我想与这个子进程并行运行几行代码 子进程完成后 我想打印一行代码 主要脚本 usr bin perl 1 print before the chil
  • 等待信号,然后继续执行

    我正在尝试制作一个程序suspends它的执行直到信号到达 然后 信号到达后我只想我的代码从原来的地方继续执行 我不希望它执行函数处理程序或任何其他内容 有没有一种简单的方法可以做到这一点 我已经奋斗了一周左右 到处阅读 但没有设法获得完全
  • 线程安全的集合类

    Java中提供了许多集合类 其中有的是线程安全的 有的是线程不安全的 线程安全的集合类有 1 Vector Vector类实现了一个 动态数组 与ArrayList相似 但Vector是同步访问的 2 Stack Stack是Vector的
  • JavaScript、node.js 在继续之前等待 socket.on 响应

    我需要从客户端的服务器获取信息 所以在服务器端 当客户端第一次连接时我得到了这个 socket on adduser function username misc code where i set num player and whatno
  • WebDriver Wait '.until(ExpectedConditions.elementToBeClickable' 仅当我将 Thread.sleep(500) 添加到代码中时才有效?

    我正在尝试使用 webdriver wait 单击页面上可见的按钮 但 webdriver 仅在添加后才能单击该按钮Thread sleep到代码 在执行代码之前 我还检查了按钮是否可见 True returns true 按钮可见性检查
  • 如何在网络驱动程序中检查页面是否已完全加载?

    我正在编写一些 Java Webdriver 代码来自动化我的应用程序 如何正确判断页面是否已加载 该应用程序也有一些 Ajax 调用 我已经声明了对 WebDriver 的隐式等待 硒会为你做到这一点 或者至少它尽力了 有时它会达不到要求
  • Android 在 AlertDialog 中等待用户输入以继续

    我看到这里讨论了这个主题 但似乎不明白如何继续 In my onCreate我有代码检查它是否是应用程序的第一次运行firstRun getPref getBoolean firstRun true 如果是第一次运行该应用程序 则会显示一个
  • 等待(长超时)和加入(长毫秒)之间的区别?

    当线程 1 在线程 2 上调用 wait 和 join 方法时 线程 1 会等待线程 2 一段时间或直到线程 2 完成 如果我们使用这些方法的重载版本 即 wait long timeout 和 join long millis 那么 在
  • 有没有办法从主活动中调用另一个自定义适配器内项目的自定义适配器的notifyDataSetChanged()?

    我一直在尝试解决这个问题 但我还没有弄清楚 在我的布局中有一个带有自定义适配器的列表视图 在每个视图中 我都有许多对象存储在名为 ViewHolder 的静态类中 一个是带有另一个自定义适配器的画廊 我的问题是 在我的 Activity 上

随机推荐

  • 【云原生 · k8s】k8s-master初始化过程讲解

    文章目录 1 k8s master初始化过程讲解 2 k8s master运行的组件查看 控制平面 官网说法 查看 3 此时主节点就可以用 4 加入k8s node到集群中 5 k8s master主节点 查看所有工作节点的信息 6 如何让
  • Python爬虫抓取岗位信息~~叮~~毕业生看过来

    众所周知爬虫是用python编程语言实现的 主要用于网络数据的抓取和处理 例如爬取豆瓣电影TOP250 爬取小说等等 而爬取岗位对于刚毕业的大学生也是非常有必要的 下面我们来看看如何实现吧 用到的编程工具是python3 7 目录 一 抓取
  • Cocos2d-x2.0 进度动画 深入分析http://www.oschina.net/question/565065_101742

    Cocos2d x2 0 进度动画 深入分析 长平狐 发表于 2013 3 19 18 39 8个月前 0回 181阅 开源中国诚邀您参加 Cloud Foundry 中国群英会 北京 上海 杭州 成都 深圳 Cocos2d x相关教程来源
  • Apache下的ArrayUtils工具类总结(操作数组)

    ArrayUtils中的方法 1 add 将给定的数据添加到指定的数组中 返回一个新的数组 2 addAll 合并两个数组 3 contains 检查该数据在该数组中是否存在 返回一个boolean值 4 getLength 返回该数组长度
  • 手把手教你快速排序(非递归)

    目录 一 实现原理 二 代码实现 c语言 今天小编带大家学习快速排序的非递归方法 当然这篇博客是基于大家已经掌握了快排的递归方法的 如果还有不会的童鞋 可以看看下面这篇博客呦 手把手教你快速排序 递归 一 实现原理 首先我们需要一个栈 我们
  • Python:数组添加数据和删除数据

    行添加 删除数据 valid tmp np append valid tmp train tmp idx axis 0 train tmp idx 和valid tmp维数相同 train tmp np delete train tmp i
  • 计算机页码格式罗马数字,word 页码 罗马数字怎么从1开始

    word 页码 罗马数字怎么从1开始以下文字资料是由 历史新知网www lishixinzhi com 小编为大家搜集整理后发布的内容 让我们赶快一起来看一下吧 word 页码 罗马数字怎么从1开始 第一步 在前几页结束的地方点 插入 gt
  • 华为OD机试真题-区块链转储系统【2023Q1】

    题目描述 区块链底层存储是一个链式文件系统 由顺序的N个文件组成 每个文件的大小不一 依次为F1 F2 Fn 随着时间的推移 所占存储会越来越大 云平台考虑将区块链按文件转储到廉价的SATA盘 只有连续的区块链文件才能转储到SATA盘上 且
  • 将安全信息应用到以下对象时发生错误:C:\Users\lenovo\Application Data无法枚举容器中的对象。访问被拒绝。

    如果找不到Application Data 打开访问权限 右键属性 gt gt 安全 gt gt 高级 更改 高级 然后 确定 gt gt 确定 gt gt 应用 然后回到 应用 这样就能进入Application Data文件夹了
  • 等待和通知机制(wait和notify)

    1 等待和通知机制的实现 wait 方法 wait 是 Object 类的方法 它的作用是使当前执行wait方法的线程进行等待 该方法将当前线程置入 预执行队列 中 并在 wait 所在的代码行处停止执行 直到接到通知或者被中断才能继续执行
  • 代表什么_鸽子飞到家里代表什么

    阅读本文前 请您先点击上面的蓝色字体 教你风水旺财运 再点击 关注 这样您就可以继续免费收到最新资讯了 每天都有分享 完全是免费订阅 请放心关注 现在可能没那么常见 但是在农村家里出现一些外来的生物还是很正常的 对我们也存在影响 对我们来说
  • 【干货】MySQL底层架构设计,你了解多少?

    很多开发同学对SQL优化如数家珍 却对MySQL架构一知半解 岂不是只见树叶 不见森林 终将陷入细节中不能自拔 今天就一块学习MySQL分层架构 深入了解MySQL底层实现原理 以及每层的作用 我们常见的SQL优化到底在哪一层做了优化 小伙
  • vs code使用power mode设置鼠标光标动效

    记录一个开发的题外话 vs code编辑器使用插件 power mode来设置鼠标光标动效 如下 1 vscode 安装 power mode插件 2 打开vscode编辑器 文件 首选项 设置 设置界面 开启power mode插件 设置
  • [Pyhon疫情大数据分析] 三.新闻信息抓取及词云可视化、文本聚类和LDA主题模型文本挖掘

    思来想去 虽然很忙 但还是挤时间针对这次肺炎疫情写个Python大数据分析系列博客 包括网络爬虫 可视化分析 GIS地图显示 情感分析 舆情分析 主题挖掘 威胁情报溯源 知识图谱 预测预警及AI和NLP应用等 希望该系列线上远程教学对您有所
  • 数据结构 算法大全 基础篇

    数据结构和算法是计算机科学中的两个重要部分 它们对于编写高效 可扩展性强的程序非常重要 数据结构是一种组织和存储数据的方式 它包括一些基本的数据结构 例如数组 链表 栈 队列 树 图等等 数据结构的选择取决于所要解决的问题和使用场景 因此需
  • centos服务器系统下安装python3并与自带的python2

    centos服务器系统下安装python3并与自带的python2 在centos中 自带有python2 因此需要经常安装python3 但是这里有一个坑 就是centos的yum是用python2写的 如果正常编译安装python3 那
  • GDB调试原理

    本地调试gdb 桌面调试主要是本地调试 以gdb为例 1 1 1 gdb调试原理 1 未执行进程调试 启用gdb调试运行gdb test的时候 在操作系统里发生了很多复杂的事情 系统首先会启动gdb进程 这个进程会调用系统函数fork 来创
  • 规则引擎Drools使用 第十四篇 Spring整合Drools

    使用Spring管理整合drools 首先需要引入依赖 然后配置spring文件 引入依赖
  • 基于stm32F103C8T6的智能门禁(毕业设计)

    刷卡 分享一期 RC522刷卡模块做的门禁系统 上面是视频呈现 功能文字说明 拓展空间非常大 识别卡号以及卡类并显示 刷管理卡 按下按键 提示刷卡录入 刷未录入的卡即可录入 刷用户卡 按下按键 提示刷卡录入 刷未录入的卡即可录入 再次刷卡
  • 【Cesium入门】一、Cesium安装部署运行

    1 介绍 CesiumJS是一个用于Web上3D地图的JavaScript库 开发者通过Cesium 实现无插件的创建三维球 Cesium通过WebGL技术实现图形的硬件加速 并且跨平台 跨浏览器 2 Cesium项目下载 1 在官网下载压