线程控制

1、join

一个线程在执行过程中,有一个方法或者一行代码需要新开的线程执行完成后才继续往下执行时,用join,比如:

Thread o1 = new Thread(new Runnable() {
            @Override
            public void run() {
                for(int i =0;i<1000;i++){
                    System.out.println("A"+i);
                }
            }
        });

Thread o2 = new Thread(new Runnable() {
    @Override
    public void run() {
        System.out.println("111");
        o1.start();
        try {
            o1.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("o1执行完毕");
        for(int i =0;i<1000;i++){
            System.out.println("B"+i);
        }
    }
});

o2.start()

在o2线程中,用了o1.join(),所以,线程执行到这里,需要等待o1执行完成之后,才继续往下走

2、wait/notifyAll

wait必须在同步代码块中使用,也就是synchronized(s){},s.wait(),s.notify(),  当wait()时,会释放当前获得的锁,且让出cpu,直到notify()调用之后,才重新尝试获取锁,执行后面代码。比如:

Student s = new Student();
        Thread t6 = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (s){
                    for(int i =1;i<11;i++){
                        System.out.println(Thread.currentThread().getName()+"正在下载图片:"+i+"0%");
                    }
                    System.out.println("图片下载完毕");
                    s.setAge(14);
                    s.notify();
                }

            }
        });
        Thread t7 = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (s){
                    System.out.println("等待图片下载完成");
                    s.setName("zhangsan");
                    try {
                        s.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("显示图片");
                }

            }
        });

注意:多线程中,尽量使用while 而不是使用if,原因是当wait()的线程,被notify唤醒之后,如果使用if,是不会再次进行if判断,而是直接执行wait()后面的方法,如果使用while,会先进行判断,再执行。下面是一个例子:

public class ListAddRemove {
    public static final Object object = new Object();
    public static List<Integer> list = new ArrayList<>();


    public static void main(String[] args) {
        AddThread addThread = new AddThread();
        RemoveThread removeThread = new RemoveThread();
        Thread t1 = new Thread(addThread);
        Thread t2 = new Thread(removeThread);
        Thread t3 = new Thread(removeThread);

        t2.start();
        t3.start();
        t1.start();
    }
}

class RemoveThread implements Runnable {

    private final Object object = ListAddRemove.object;

    @Override
    public void run() {
        synchronized (object) {
            System.out.println(Thread.currentThread().getName() + "删除线程开始执行");
            if (ListAddRemove.list.size() == 0) {//此处如果改成while,则不会报错
                try {
                    System.out.println(Thread.currentThread().getName() + "删除线程发现lit为空,调用wait()方法");
                    object.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            ListAddRemove.list.remove(0);
            System.out.println(Thread.currentThread().getName()+"删除完成");
        }
    }
}

class AddThread implements Runnable {
    private final Object object = ListAddRemove.object;

    @Override
    public void run() {
        synchronized (object) {
            System.out.println("add线程执行");
            ListAddRemove.list.add(new Random().nextInt());
            System.out.println("add线程数据添加完成,调用notifyAll()");
            object.notifyAll();
            System.out.println("add线程调用notifyAll()后");
        }
    }
}

上述代码是一个典型的生产者消费者模式,一个生产者向数组添加一个元素,两个消费者从数据中删除元素,生产者添加元素后,通知两个消费者删除元素,如果使用if (ListAddRemove.list.size() == 0),则会出现角标越界异常,因为如果使用if,消费者被唤醒之后会直接执行wait()后面的代码,而如果使用while,则会先对while进行判断,再执行后面的代码。所以上述代码将if (ListAddRemove.list.size() == 0) 改为while (ListAddRemove.list.size() == 0)之后,就不会出现角标越界异常,删除线程就会继续等待。

当方法wait()被执行后,锁自动被释放,但执行完notify()方法后,锁不会自动释放。必须执行完notify()方法所在的synchronized代码块后才释放。

3、CountDownLatch(计数器)

CountDownLatch的构造方法传入一个int值,指定计数器的个数。计数器的作用类似于join,当调用计数器的await()方法之后,当前线程阻塞,直到计数器的个数为0后(调用countDown()方法,计数器的个数会减1),才继续执行下面的代码。示例如下:

/**
 * 计数器
 * 构造方法传入一个参数,指定计数器的计数个数
 */
public class CountDownLatchDemo implements Runnable {
    private static CountDownLatch end = new CountDownLatch(10);
    @Override
    public void run() {
        try{
            Thread.sleep(1000);
            System.out.println(Thread.currentThread().getName()+"已完成检查");
            //通知线程已经完成任务,计数器可以减1了
            end.countDown();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        CountDownLatchDemo demo = new CountDownLatchDemo();
        ExecutorService service = Executors.newFixedThreadPool(10);
        for(int i =0;i<10;i++){
            service.submit(demo);
        }
        end.await();
        System.out.println("全部检查完成");
        service.shutdown();
    }
}

4、Semaphore (信号量)

 信号量semaphore ,用于指定某几个线程可以同时访问某一个临界资源,下面的案例是线程池维护了30个线程,但是只有5个线程可以同时访问临界资源,如果将参数改为1,则可以起到互斥锁的作用,第二个boolean参数表示是否是线程公平的,所谓的公平锁就是先等待的线程先获得锁

/**
 * 信号量semaphore
 * acquire() 类似lock()
 * tryAcquire(long timeout,TmeUnit unit) 类似tryLock()
 * tryAcquire()
 * release()  释放锁,类似unlock()
 */
public class SemaphoreThread implements Runnable {
    private Semaphore semaphore = new Semaphore(5,true);
    @Override
    public void run() {
        try{
            semaphore.acquire();
            Thread.sleep(1000);
            System.out.println("done");
            semaphore.release();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        SemaphoreThread semaphoreThread = new SemaphoreThread();
        ExecutorService executorService = Executors.newFixedThreadPool(30);
        for(int i =0;i<30;i++){
            executorService.submit(semaphoreThread);
        }

    }
}

Semaphore可以用来做接口限流(延伸使用Semaphore和RateLimiter做接口限流)

5、Interrupt 线程中断

线程中断可以使用Thread.stop()方法,但是该方法会强制中断当前线程,如果当前线程正在写入数据,强制中断后,就会破坏数据,JDK目前已经废弃了该方法,建议使用Thread.Interrupt()方法来中断线程。该方法执行后,会通知当前线程,你要中断了,当前线程收到通知后,不会立即停止,会将代码走完,走完之后,可以使用Thread.isInterrupt()方法来判断当前线程是否已经收到中断通知,如果返回true,则表示已经收到中断通知,下面是示例:

public class InterruptThread implements Runnable {
    @Override
    public void run() {
        while (true){
            System.out.println("1");
            if(Thread.currentThread().isInterrupted()){
                System.out.println("线程收到停止通知,线程停止");
                break;
            }
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }

    public static void main(String[] args) {
        InterruptThread i = new InterruptThread();
        Thread t = new Thread(i);
        t.start();
        t.interrupt();
    }
}

注意:如果线程在sleep的时候收到了中断通知,那么sleep会抛出异常,同时清除中断状态。所以在catch里,要再进行interrupt操作。

暂时只想到这么多,后面有想到的就补充上

【永磁同步电机】基于模型预测控制MPC的永磁同步电机非线性终端滑模控制仿真研究(Simulink&Matlab代码实现)内容概要:本文围绕永磁同步电机(PMSM)的高性能控制展开,提出了一种结合模型预测控制(MPC)与非线性终端滑模控制(NTSMC)的先进控制策略,并通过Simulink与Matlab进行系统建模与仿真验证。该方法旨在克服传统控制中动态响应慢、鲁棒性不足等问题,利用MPC的多步预测和滚动优化能力,结合NTSMC的强鲁棒性和有限时间收敛特性,实现对电机转速和电流的高精度、快速响应控制。文中详细阐述了系统数学模型构建、控制器设计流程、参数整定方法及仿真结果分析,展示了该复合控制策略在抗干扰能力和动态性能方面的优越性。; 适合人群:具备自动控制理论、电机控制基础知识及一定Matlab/Simulink仿真能力的电气工程、自动化等相关专业的研究生、科研人员及从事电机驱动系统开发的工程师。; 使用场景及目标:①用于深入理解模型预测控制与滑模控制在电机系统中的融合应用;②为永磁同步电机高性能控制系统的仿真研究与实际设计提供可复现的技术方案与代码参考;③支撑科研论文复现、课题研究或工程项目前期验证。; 阅读建议:建议读者结合提供的Simulink模型与Matlab代码,逐步调试仿真环境,重点分析控制器设计逻辑与参数敏感性,同时可尝试在此基础上引入外部扰动或参数变化以进一步验证控制鲁棒性。
一种基于有效视角点方法的相机位姿估计MATLAB实现方案 该算法通过建立三维空间点与二维图像点之间的几何对应关系,实现相机外部参数的精确求解。其核心原理在于将三维控制点表示为四个虚拟基点的加权组合,从而将非线性优化问题转化为线性方程组的求解过程。 具体实现步骤包含以下关键环节:首先对输入的三维世界坐标点进行归一化预处理,以提升数值计算的稳定性。随后构建包含四个虚拟基点的参考坐标系,并通过奇异值分解确定各三维点在该基坐标系下的齐次坐标表示。接下来建立二维图像点与三维基坐标之间的投影方程,形成线性约束系统。通过求解该线性系统获得虚拟基点在相机坐标系下的初步坐标估计。 在获得基础解后,需执行高斯-牛顿迭代优化以进一步提高估计精度。该过程通过最小化重投影误差来优化相机旋转矩阵和平移向量。最终输出包含完整的相机外参矩阵,其中旋转部分采用正交化处理确保满足旋转矩阵的约束条件。 该实现方案特别注重数值稳定性处理,包括适当的坐标缩放、矩阵条件数检测以及迭代收敛判断机。算法能够有效处理噪声干扰下的位姿估计问题,为计算机视觉中的三维重建、目标跟踪等应用提供可靠的技术基础。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值