十一、定时器

1、定时器是什么

定时器:

定时器也是软件开发中的⼀个重要组件. 类似于⼀个 "闹钟". 达到⼀个设定的时间之后, 就执⾏某个指定 好的代码.

定时器是⼀种实际开发中⾮常常⽤的组件

举个例子:

⽐如⽹络通信中, 如果对⽅ 500ms 内没有返回数据, 则断开连接尝试重连.

类似于这样的场景就需要⽤到定时器.

package thread_demo;

import java.util.Timer;
import java.util.TimerTask;

public class Demo37 {
    public static void main(String[] args) {
        Timer timer =new Timer();

        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println("hello 3000");
            }
        },3000);
        System.out.println("hello main");

        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println("hello 2000");
            }
        },2000);

        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println("hello 1000");
            }
        },1000);


    }
}

运行结果:

 

2、模拟实现定时器

定时器的构成

• ⼀个带优先级队列(不要使⽤ PriorityBlockingQueue, 容易死锁!)

当管理多个任务的时候,需要确保,时间最早的任务,最先执行,通过遍历的方式,找到时间最早.使用优先队列

• 队列中的每个元素是⼀个 Task 对象.

• Task 中带有⼀个时间属性, 队⾸元素就是即将要执⾏的任务

时间戳:

计算机中,使用时间戳来表示“时刻”

以1970年1月1日0时0分0秒基准时刻
计算当前时刻和基准时刻的,秒数之差 (毫秒/微秒)

• 同时有⼀个 worker 线程⼀直扫描队⾸元素, 看队⾸元素是否需要执⾏

代码实现

1. Timer 类提供的核⼼接⼝为 schedule, ⽤于注册⼀个任务, 并指定这个任务多⻓时间后执⾏.

class  Mytimer {
    private PriorityQueue<MyTimerTask> queue = new PriorityQueue<>();


    public void schedule(Runnable task, long delay) {
       
    }

}

 2. MyTimeTask 类⽤于描述⼀个任务(作为 Timer 的内部类).

⾥⾯包含⼀个 Runnable 对象和⼀个 time(毫秒时 间戳) 这个对象需要放到 优先队列 中. 因此需要实现 Comparable 接⼝.

class MyTimerTask implements Comparable<MyTimerTask> {
    private Runnable task;

    private long time;

    public MyTimerTask(Runnable task, long time) {
        this.task = task;
        this.time = time;
    }


    @Override
    public int compareTo(MyTimerTask o) {
        return (int) (this.time - o.time);
    }

    public long getTime() {
        return time;
    }

    public void run() {
        task.run();
    }


}

 3. MyTimer 实例中, 通过 PriorityQueue 来组织若⼲个 Task 对象. 通过 schedule 来往队列中插⼊⼀个个 Task 对象.

class  Mytimer {
    private PriorityQueue<MyTimerTask> queue = new PriorityQueue<>();

    private Object locker = new Object();

    public void schedule(Runnable task, long delay) {
        synchronized (locker) {
            MyTimerTask timerTask = new MyTimerTask(task, System.currentTimeMillis() + delay);
            queue.offer(timerTask);
            locker.notify();
        }
    }

}

 4. Timer 类中存在⼀个 worker 线程, ⼀直不停的扫描队⾸元素, 看看是否能执⾏这个任务. 所谓 "能执⾏" 指的是该任务设定的时间已经到达了.

class  Mytimer {
    private PriorityQueue<MyTimerTask> queue = new PriorityQueue<>();

    private Object locker = new Object();

    public void schedule(Runnable task, long delay) {
        synchronized (locker) {
            MyTimerTask timerTask = new MyTimerTask(task, System.currentTimeMillis() + delay);
            queue.offer(timerTask);
            locker.notify();
        }
    }

    public Mytimer() {
        Thread t = new Thread(() -> {
            try {
                while (true) {
                    synchronized (locker) {
                        while (queue.isEmpty()) {
                            locker.wait();
                        }
                        MyTimerTask task = queue.peek();
                        if (System.currentTimeMillis() < task.getTime()) {
                            locker.wait(task.getTime() - System.currentTimeMillis());
                        } else {
                            task.run();
                            queue.poll();
                        }
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        });

        t.start();
    }
}

完整代码: 

package thread_demo;


import java.util.Objects;
import java.util.PriorityQueue;

class MyTimerTask implements Comparable<MyTimerTask> {
    private Runnable task;

    private long time;

    public MyTimerTask(Runnable task, long time) {
        this.task = task;
        this.time = time;
    }


    @Override
    public int compareTo(MyTimerTask o) {
        return (int) (this.time - o.time);
    }

    public long getTime() {
        return time;
    }

    public void run() {
        task.run();
    }


}

class Mytimer {
    private PriorityQueue<MyTimerTask> queue = new PriorityQueue<>();

    private Object locker = new Object();

    public void schedule(Runnable task, long delay) {
        synchronized (locker) {
            MyTimerTask timerTask = new MyTimerTask(task, System.currentTimeMillis() + delay);
            queue.offer(timerTask);
            locker.notify();
        }
    }

    public Mytimer() {
        Thread t = new Thread(() -> {
            try {
                while (true) {
                    synchronized (locker) {
                        while (queue.isEmpty()) {
                            locker.wait();
                        }
                        MyTimerTask task = queue.peek();
                        if (System.currentTimeMillis() < task.getTime()) {
                            locker.wait(task.getTime() - System.currentTimeMillis());
                        } else {
                            task.run();
                            queue.poll();
                        }
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        });

        t.start();
    }
}

public class Demo38 {
    public static void main(String[] args) {

        Mytimer mytimer = new Mytimer();

        mytimer.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello 3000");
            }
        }, 3000);

        mytimer.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello 2000");
            }
        }, 2000);

        mytimer.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello 1000");
            }
        }, 1000);
    }
}

在STM32中使用定时器功能可以通过STM32CubeMx软件进行配置。首先,你需要准备好STM32开发板(例如STM32F103VET6)和Keil软件。然后,你可以按照以下步骤进行配置: 1. 打开STM32CubeMx软件,创建一个新的工程。 2. 在"Pinout & Configuration"选项卡中,选择你要使用的引脚。对于按键,你可以选择PA0和PC13;对于LED,你可以选择PB0、PB1和PB5。 3. 在"Configuration"选项卡中,找到定时器相关的配置选项。根据你的需求,选择定时器的模式(例如基本定时器或PWM模式)和时钟源。 4. 配置定时器的预分频和计数周期。根据你的需求,设置预分频和计数周期来实现所需的定时周期。例如,如果你想要1ms的定时器,可以将预分频设置为(24-1),计数周期设置为(1000-1)。 5. 保存配置并生成代码。 6. 在生成的代码中,你可以找到定时器相关的函数,例如HAL_TIM_Base_MspInit()、HAL_TIM_Base_Start_IT()和HAL_TIM_PWM_Start()等。这些函数可以帮助你初始化定时器、开启定时器中断或PWM模式等功能。 通过以上步骤,你可以在STM32中配置和使用定时器功能。请注意,具体的配置和函数可能会根据你使用的STM32型号和需求而有所不同。因此,你需要根据实际情况进行相应的配置和调整。\[1\]\[2\]\[3\] #### 引用[.reference_title] - *1* [STM32CubeMX之定时器PWM输出](https://blog.csdn.net/weixin_44453694/article/details/122351580)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [STM32CubeMX——定时器之定时功能](https://blog.csdn.net/lcp0633/article/details/111145199)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [STM32CubeMX学习四 之定时器配置](https://blog.csdn.net/weixin_42648781/article/details/126670397)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值