堆栈花园的多线程学习备忘录——wait和notify

本文详细介绍了Java中多线程的等待/通知机制,包括其原理、如何使用Object类的wait()和notify()方法实现线程间的同步,以及通过实例演示两个线程交替打印奇数和偶数的过程。
一、等待/通知机制

什么是等待/通知机制?

  • 在单线程中,如果要执行的代码需要满足一定条件才能执行,可以放到if语句块里。
  • 但在多线程中,可能A线程的执行的条件暂时没有满足,稍后B线程执行到一定程度,使得A线程的执行条件满足,再执行完A线程。可以将A线程先暂停,直到条件满足后再将A线程唤醒。
二、 等待通知机制的实现

Object类中有一个wait()方法,可以使执行的当前代码线程等待,暂停执行,直到接到通知,或者被中断。
注意:
(1)wait()方法只能在同步代码块中由锁对象调用。
(2)调用wait()方法后,当前线程会暂停,并释放锁对象。

Object类的notify()可以唤醒线程,该方法也必须在同步代码块中由锁对象调用(不然会抛异常)。如果有多个等待的线程,notify()方法只能唤醒其中一个。在同步代码块中调用notify()方法,不会立马释放锁对象,需要等当前同步代码块执行完,才会释放,所以我们一般把notify()放在同步代码块的最后。

  • 通过等待通知机制,实现2个线程交换打印输出奇数和偶数。
//先写一个多个线程需要共享的同一个对象的类。
public class Num{
    int i;
}

//专门打印偶数的线程
public class Even implements Runnable{
    Num num;
    public Even(Num num) {
        this.num = num;
    }
    @Override
    public void run() {
        while (num.i < 100){
            synchronized (num){
                if(num.i % 2 != 0){
                    try {
                        num.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println(Thread.currentThread().getName() + "---->" + num.i);
                num.i++;
                num.notify();
            }
        }
    }
}

//专门打印奇数的线程
public class Odd implements Runnable{
    Num num;
    public Odd(Num num) {
        this.num = num;
    }
    @Override
    public void run() {
        while(num.i < 100){
            synchronized (num){
                if(num.i % 2 == 0){
                    try {
                        num.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println(Thread.currentThread().getName() + "---->" + num.i);
                num.i++;
                num.notify();
            }
        }
    }
}

//main方法测试一下
public static void main(String[] args) {
        Num num = new Num();
        Thread t1 = new Thread(new Odd(num));
        Thread t2 = new Thread(new Even(num));
        t1.setName("t1");
        t2.setName("t2");
        t1.start();
        t2.start();
    }

分析一下以上代码:

  • 我们将奇数线程记作A线程,偶数线程记作B线程

当创建出这两个线程后,启动他们,如果A抢到了时间片,那么由于i的初始值为0,符合A中代码块的if语句,所以执行锁对象的wait方法,A开始等待(即使A第二次又抢到了时间片,还是会继续执行wait方法开始等待)。当B抢到了时间片,由于i不满足if语句,所以i自增,再执行锁对象的notify方法,另外一个共享锁对象的A就会被唤醒(若有多个这样的A线程,究竟唤醒哪个线程是不一定的),开始执行,由于这时的i是1,不满足if语句,所以i自增,并唤醒另一个共享锁对象的B。周而复始,实现了两个线程交替打印奇数和偶数。

三、 interrupt()方法会中断wait()
  • 当线程处于wait()等待状态时,调用线程对象的interrupt()方法会中断线程的等待状态。(是通过抛异常的方式中断,InterruptedException异常)
四、notify()和notifyAll()
  • notify()一次只能唤醒一个线程,如果有多个等待的线程,只会随机唤醒其中的某一个(这被称为信号丢失),想要所有等待线程都被唤醒,需要调用notifyAll()。
提供了基于BP(Back Propagation)神经网络结合PID(比例-积分-微分)控制策略的Simulink仿真模型。该模型旨在实现对杨艺所著论文《基于S函数的BP神经网络PID控制器及Simulink仿真》中的理论进行实践验证。在Matlab 2016b环境下开发,经过测试,确保能够正常运行,适合学习研究神经网络在控制系统中的应用。 特点 集成BP神经网络:模型中集成了BP神经网络用于提升PID控制器的性能,使之能更好地适应复杂控制环境。 PID控制优化:利用神经网络的自学习能力,对传统的PID控制算法进行了智能调整,提高控制精度稳定性。 S函数应用:展示了如何在Simulink中通过S函数嵌入MATLAB代码,实现BP神经网络的定制化逻辑。 兼容性说明:虽然开发于Matlab 2016b,但理论上兼容后续版本,可能会需要调整少量配置以适配不同版本的Matlab。 使用指南 环境要求:确保你的电脑上安装有Matlab 2016b或更高版本。 模型加载: 下载本仓库到本地。 在Matlab中打开.slx文件。 运行仿真: 调整模型参数前,请先熟悉各模块功能输入输出设置。 运行整个模型,观察控制效果。 参数调整: 用户可以自由调节神经网络的层数、节点数以及PID控制器的参数,探索不同的控制性能。 学习修改: 通过阅读模型中的注释查阅相关文献,加深对BP神经网络与PID控制结合的理解。 如需修改S函数内的MATLAB代码,建议有一定的MATLAB编程基础。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值