精华内容
下载资源
问答
  • 定时器原理
    2021-03-06 18:38:43

    作为程序员来说,我们可能经常会使用到spring框架去实现各种各样的需求开发,其中的一项,定时器也是经常会被使用到的,那么你是否清楚其原理是什么呢?

    首先我们来看看简单定时器实现方法:用ScheduledExecutorService接口的方式实现:public interface ScheduledExecutorService extends ExecutorService

    {

    //创建并执行在给定延迟后启用的一次性操作。

    ScheduledFuture  schedule(Runnable command, long delay, TimeUnit unit);

    创建并执行在给定延迟后启用的 ScheduledFuture。

     ScheduledFuture  schedule(Callable  callable, long delay, TimeUnit unit);

    //创建并执行一个在给定初始延迟后首次启用的定期操作, 后续操作具有给定的周期;

    //也就是将在 initialDelay 后开始执行, 然后在 initialDelay + period 后执行,

    //接着在 initialDelay + 2 * period 后执行, 依此类推。 如果任务的任何一个执行遇到异常, 则后续执行都会被取消。

    // 否则, 只能通过执行程序的取消或终止方法来终止该任务。 如果此任务的任何一个执行要花费比其周期更长的时间, 则将推迟后续执行, 但不会同时执行。

    ScheduledFuture  scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit);

    //创建并执行一个在给定初始延迟后首次启用的定期操作, 随后, 在每一次执行终止和下一次执行开始之间都存在给定的延迟。 如果任务的任一执行遇到异常, 就会取消后续执行。 否则, 只能通过执行程序的取消或终止方法来终止该任务。

    ScheduledFuture  scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit);

    }

    用法示例如下:import static java.util.concurrent.TimeUnit.*;

    class BeeperControl

    {

    private final ScheduledExecutorService scheduler =

    Executors.newScheduledThreadPool(1);

    public void beepForAnHour()

    {

    final Runnable beeper = new Runnable()

    {

    public void run()

    {

    System.out.println("beep");

    }

    };

    final ScheduledFuture  beeperHandle =

    scheduler.scheduleAtFixedRate(beeper, 10, 10, SECONDS);

    scheduler.schedule(new Runnable()

    {

    public void run()

    {

    beeperHandle.cancel(true);

    }

    }, 60 * 60, SECONDS);

    }

    }

    具体说明如下所示:

    ScheduledAnnotationBeanPostProcessor

    其核心方法是,Object postProcessAfterInitialization(final Object bean, String

    beanName) ,其主要功能是负责@Schedule注解的扫描,构建ScheduleTask 。

    其核心方法是,onApplicationEvent(ContextRefreshedEvent event)

    其功能是,在spring容器加载完毕之后调用,ScheduleTask向ScheduledTaskRegistrar中注册,

    调用ScheduledTaskRegistrar.afterPropertiesSet() 。

    ScheduledTaskRegistrar

    其核心方法是,void afterPropertiesSet(),功能就是初始化所有定时器,并且启动定时器 。

    TaskScheduler

    主要的实现类有三个,它们分别是ThreadPoolTaskScheduler,

    ConcurrentTaskScheduler和TimerManagerTaskScheduler 。

    这些类的作用最主要是将task和executor使用ReschedulingRunnable包装起来并且进行了生命周期管理。

    其核心方法是,ScheduledFuture schedule(Runnable task, Trigger trigger) 。

    那么以上就是有关spring定时器原理的所有内容了,还想了解更多的java架构师信息,记得关注本站消息哦。

    推荐阅读:

    更多相关内容
  • 实现实现quartz定时器及定时器及quartz定时器原理介绍定时器原理介绍Quartz是一个大名鼎鼎的Java版开源定时调度器,功能强悍,使用方便,下面我们看看如何使用它一、核心概念一、核心概念 Quartz的原理不是很复杂,...
  • 时钟周期:  时钟周期也叫振荡周期或晶振周期,即晶振的单位时间发出的脉冲数,一般有外部的振晶产生,比如12MHZ=12×10的6次方,即每秒发出12000000个脉冲信号,那么发出一个脉冲的时间就是时钟周期,也就是1/12...
  • STC单片机计数器和定时器原理及实现 主讲何宾 Email hebin@ 2016.03 计数器/定时器模块简介 STC15W4K32S4系列单片机设置了5个16位定时器/计数器即T0 T1T2T3以及T4这5个16位定时器/计数器可以配置为计数工 作模式或者...
  • 定时器原理

    2013-11-17 21:54:47
    本图片是应用于STM32的定时器原理图,图片清晰,结构表达清楚,希望大家喜欢
  • 定时器原理

    千次阅读 2020-06-16 09:02:03
    1. 定时器介绍 程序里的定时器主要实现的功能是在未来的某个时间点执行相应的逻辑。在定时器模型中,一般有如下几个定义。 interval:间隔时间,即定时器需要在...接下来我们一起看下这些方法的具体实现原理。 ..

    1. 定时器介绍

    程序里的定时器主要实现的功能是在未来的某个时间点执行相应的逻辑。在定时器模型中,一般有如下几个定义。 

    interval:间隔时间,即定时器需要在interval时间后执行
    StartTimer:添加一个定时器任务
    StopTimer:结束一个定时器任务
    PerTickBookkeeping: 检查定时器系统中,是否有定时器实例已经到期,相当于定义了最小时间粒度。

    常见的实现方法有如下几种:

    链表
    排序链表
    最小堆
    时间轮 

    接下来我们一起看下这些方法的具体实现原理。

     

    2. 定时器实现方法

    2.1 链表实现


    链表的实现方法比较粗糙。链表用于存储所有的定时器,每个定时器都含有interval 和 elapse 两个时间参数,elapse表示当前被tickTimer了多少次。当elapse 和interval相等时,表示定时器到期。

    在此方案中,添加定时器就是在链表的末尾新增一个节点,时间复杂度是 O(1)。

    如果想要删除一个定时器的话,我们需要遍历链表找到对应的定时器,时间复杂度是O(n)。

    此方案下,每隔elapse时间,系统调用信号进行超时检查,即PerTickBookkeeping。每次PerTickBookkeeping需要对链表所有定时器进行 elapse++,因此可以看出PerTickBookkeeping的时间复杂度是O(N)。

    可以看出此方案过于粗暴,所以使用场景极少。

    2.2 排序双向链表实现


    排序双向链表是在链表实现上的优化。优化思路是降低时间复杂度。

    首先,每次PerTickBookkeeping需要自增所有定时器的elapse变量,如果我们将interval变为绝对时间,那么我们只需要比较当前时间和interval时间是否相等,减少了对每个定时器的操作。

    如果不需要对每个定时器进行操作,我们将定时器进行排序,那么每次PerTickBookkeeping都只需要判断第一个定时器,时间复杂度为O(1)。

    相应的,为了维持链表顺序,每次新增定时器需要进行链表排序时间复杂度为 O(N)。

    每次删除定时器时,由于会持有自己节点的引用,所以不需要查找其在链表中所在的位置,所以时间复杂度为O(1),双向链表的好处。

    图1 双向链表实现示意图

     

    2.3 时间轮实现


    相信上一篇文章《构建企业级业务高可用的延时消息中台》我们已经对时间轮有了很深刻的了解。时间轮示意图如下:

    图2 时间轮

    时间轮的数据结构是数组 + 链表。 

    他的时间轮为数组,新增和删除一个任务,时间复杂度都是O(1)。

    PerTickBookkeeping每次转动一格,时间复杂度也是O(1)。

    2.4 最小堆实现


    最小堆是堆的一种, (堆是一种二叉树), 指的是堆中任何一个父节点都小于子节点, 子节点顺序不作要求。

    二叉排序树(BST)指的是: 左子树节点小于父节点, 右子树节点大于父节点, 对所有节点适用

     

     

    图3 最小堆

    树的基本操作是插入节点和删除节点。对最小堆而言,为了将一个元素X插入最小堆,我们可以在树的下一个空闲位置创建一个空穴。如果X可以放在空穴中而不被破坏堆的序,则插入完成。否则就执行上滤操作,即交换空穴和它的父节点上的元素。不断执行上述过程,直到X可以被放入空穴,则插入操作完成。

    因此我们可以知道最小堆的插入时间复杂度是O(lgN)。

    最小堆的删除和插入逻辑基本类似,如果不做优化,时间复杂度也是O(lgN),但是实际实现方案上,做了延迟删除操作,时间复杂度为O(1)。

    延迟删除即设置定时器的执行回调函数为空,每次最小堆超时,将触发pop_heap,pop会重新调整最小堆,最终删除的定时器将调整到堆顶,但是回调函数不处理。

    可以看到PerTickBookkeeping只处理堆顶定时器,时间复杂度O(1)。

    最小堆可以使用数组来进行表示,数组中,当前下标n的左子节点为2N + 1,当前下标n的右子节点小标为2N + 2。

    图4 最小堆的数组表示

     

    3. 定时器不同实现对比

    3.1 时间复杂度对比


    图5 不同实现时间复杂度

    从上面的介绍来看,时间轮的时间复杂度最小、性能最好。

    3.2 使用场景来看

    在任务量小的场景下:最小堆实现,可以根据堆顶设置超时时间,数组存储结构,节省内存消耗,使用最小堆可以得到比较好的效果。而时间轮定时器,由于需要维护一个线程用来拨动指针,且需要开辟一个bucket数组,消耗内存大,使用时间轮会较为浪费资源。

    在任务量大的场景下:最小堆的插入复杂度是O(lgN), 相比时间轮O(1) 会造成性能下降。更适合使用时间轮实现。

    在业界,服务治理的心跳检测等功能需要维护大量的链接心跳,因此时间轮是首选。

    展开全文
  • SYSTICK滴答定时器及定时器原理
  • 51单片机定时原理介绍,其中原理由代码写成
  • JS定时器原理及案例

    2021-07-08 15:02:16
    JS定时器原理及案例JavaScript精选案例前言一、定时器二、定时器的使用1.定时器2.清除定时器三、案例1.倒计时2.使用和清除定时器3.发送短信总结 前言 JS中定时器并不算难点,但是我还是拿出来讲,过于经典的案例...


    前言

    JS中定时器并不算难点,但是我还是拿出来讲,过于经典的案例往往是最为基础的知识点,仅供参考学习。


    一、定时器

    1. setTimeout(code,millisec):只执行 code 一次。
    2. setInterval(code,millisec):会不停地调用函数,直到 clearInterval() 被调用或窗口被关闭。

    定时器注释

    1. clearTimeout() :可取消由 setTimeout() 方法设置的 timeout。
    2. clearInterval() :可取消由 setInterval() 设置的 timeout。

    定时器非常好理解,set就是定时器,clear就是清除定时器,timeout就是定时器只用一次,interval就是循环使用。

    二、定时器的使用

    1.定时器

    代码如下(示例):

    <body>
    <script>
        function time() {
            alert('倒计时时间到')
        }
        var times = setTimeout(time,3000);
    </script>
    </body>
    

    倒计时弹窗

    2.清除定时器

    <body>
    <script>
        function time() {
            alert('倒计时时间到')
        }
        var times = setTimeout(time,3000);
        clearInterval(times);
    </script>
    </body>
    

    setInterval()和cleaInterval()的原理也是一样的,我就不在这里写了

    三、案例

    1.倒计时

    代码如下(示例):

        <style>
            div {
                margin: 200px;
            }
    
            span {
                display: inline-block;
                width: 40px;
                height: 40px;
                background-color: #333;
                font-size: 20px;
                color: #fff;
                text-align: center;
                line-height: 40px;
            }
        </style>
    </head>
    
    <body>
        <div>
            <span class="hour">1</span>
            <span class="minute">2</span>
            <span class="second">3</span>
        </div>
        <script>
            // 1. 获取元素
            var hour = document.querySelector('.hour'); // 小时的黑色盒子
            var minute = document.querySelector('.minute'); // 分钟的黑色盒子
            var second = document.querySelector('.second'); // 秒数的黑色盒子
            var inputTime = +new Date('2021-7-9 00:00:00'); // 返回的是用户输入时间总的毫秒数
            countDown(); // 我们先调用一次这个函数,防止第一次刷新页面有空白
            // 2. 开启定时器
            setInterval(countDown, 1000);
    
            function countDown() {
                var nowTime = +new Date(); // 返回的是当前时间总的毫秒数
                var times = (inputTime - nowTime) / 1000; // times是剩余时间总的秒数
                var h = parseInt(times / 60 / 60 % 24); //时
                h = h < 10 ? '0' + h : h;
                hour.innerHTML = h; // 把剩余的小时给 小时黑色盒子
                var m = parseInt(times / 60 % 60); // 分
                m = m < 10 ? '0' + m : m;
                minute.innerHTML = m;
                var s = parseInt(times % 60); // 当前的秒
                s = s < 10 ? '0' + s : s;
                second.innerHTML = s;
            }
        </script>
    </body>
    

    效果图如下:
    倒计时效果图

    2.使用和清除定时器

    代码如下(示例):

    <body>
    <button class="begin">开启定时器</button>
    <button class="stop">停止定时器</button>
    <p></p> 
    <script>
        var begin = document.querySelector('.begin');
        var stop = document.querySelector('.stop');
        var p  = document.querySelector('p');
        var timer = null; // 全局变量  null是一个空对象
        begin.addEventListener('click', function() {
            timer = setInterval(function() {
                p.innerHTML+='起飞!';
            }, 1000);
        })
        stop.addEventListener('click', function() {
            clearInterval(timer);
        })
    </script>
    </body>
    

    效果图如下:
    在这里插入图片描述

    3.发送短信

    代码如下(示例):

    <body>
    <label>
        手机号码:
        <input type="number">
    </label>
    <button>发送</button>
        <script>
            // 按钮点击之后,会禁用 disabled 为true 
            // 同时按钮里面的内容会变化, 注意 button 里面的内容通过 innerHTML修改
            // 里面秒数是有变化的,因此需要用到定时器
            // 定义一个变量,在定时器里面,不断递减
            // 如果变量为0 说明到了时间,我们需要停止定时器,并且复原按钮初始状态
            var btn = document.querySelector('button');
            var time = 3; // 定义剩下的秒数
            btn.addEventListener('click', function() {
                btn.disabled = true;
                var timer = setInterval(function() {
                    if (time == 0) {
                        // 清除定时器和复原按钮
                        clearInterval(timer);
                        btn.disabled = false;
                        btn.innerHTML = '发送';
                    } else {
                        btn.innerHTML = '还剩下' + time + '秒';
                        time--;
                    }
                }, 1000);
    
            })
        </script>
    </body>
    

    效果图如下:
    在这里插入图片描述

    发送短信案例较为简单,我会在另一篇文章中更为详细的去使用定时器


    总结

    定时器的原理和案例都较为简单,但是在后面复杂的页面设计中,希望大家能够将其掌握,不要因为页面复杂而将定时器搞的复杂,这样就得不偿失了。

    如果文章对你有帮助的话,请给我一个小小的点赞一波哦!每个赞和评论都是我编写文章的动力哦!

    展开全文
  • 原理: 首先JS线程读取到setTimeout定时器,这个时候就会执行浏览器的线程,然后跳过定时器继续执行,这个时候你就看到了弹出框的内容为测试,然后因为定时器的时间为0,所以一执行定时器线程就会即可将弹出框为...

     

    JavaScript是一门基于对象的弱类型语言,它作为浏览器脚本语言,主要用途是负责与页面的交互,以及操作DOM,它的执行环境是单线程的,默认情况JS是同步加载的,也就是 JS的加载是阻塞的,也就是说同一时间只能完成一件事,只能自上而下执行,万一上一行解析代码的时间很长,那么下面的代码就会被阻塞。对于用户而言,阻塞就意味着"卡死",这样就导致了很差的用户体验。

    为了解决这个问题,利用多核CPU的计算能力,于是出现了同步和异步

    同步操作,任务遵循队列顺序异步操作,就相当于并线了,因此异步任务不具有阻塞效应。同步任务都是在主线程中执行,形成了一个执行栈,直到主线程空闲时,才会去事件队列中查看是否有可执行的异步任务,如果有就推入主进程中。

    JS是通过回调函数实现异步的

    一旦用了setTimeout(),里面的回调函数就是异步代码,加入了任务队列,延时调用一个函数不马上执行,而是要等待主队列为空,并达到定的延时时间才会执行,而且只会执行一次。

    举个栗子:

     setTimeout(function(){
          console.log("1")
     },500)
          console.log("2")
     setTimeout(function(){
          console.log("3")
     },300)
      setTimeout(function(){
         console.log("5")
     },0)
         console.log("4")

     

    从输出结果中,我们就可以看书JS执行的顺序,2和4都为主队列的同步任务,一开始就执行,执行顺序是从上到下。

    setTimeout()中的函数,无论写在JS代码中的哪个位置,设置的时间即使是0,都为异步执行,在任务队列中,从主线程执行一开始,就进行计时,一旦主线程空闲,时间短的就立即加入到主线程开始执行,时间长的依然在等待。所以根据设定的等待时间,执行顺序为5,3,1

    利用setInterval()实现异步执行

    定时器的执行原理与延时器相似,只是不清除定时器,他就会反复执行。

    异步执行的两个必要条件就是:

    1.  主队列空闲     
    2.  到达执行时间

    通过上面的例子大家应该就懂了定时器的执行规则,下面我们再详细的分析一下为什么是这样的一个规则,他是与浏览器的执行规则有关系的。

    -------------------------------------回到主题,继续剖析------------------------------------ 

    浏览器的执行原理是什么呢?

    浏览器的多线程:

    JS是单线程的,但是对于浏览器来说JS的执行只不过是在浏览器众多现成中的一条,我们称之为JS引擎线程。而浏览器的其他线程则是通过JS引擎线程在执行到某个特定的功能之后指定给浏览器的对应线程

    同样类似的栗子:

    setTimeout(console.log('定时器!'),0);
    console.log("测试")

    这个结果大家应该都知道了,先打印测试字样,后打印定时器字样。

    原理:

    首先JS线程读取到setTimeout定时器,这个时候就会执行浏览器的线程,然后跳过定时器继续执行,这个时候你就看到了弹出框的内容为测试,然后因为定时器的时间为0,所以一执行定时器线程就会即可将弹出框为定时器字样的任务添加到主线程(JS引擎线程)的队列之后,等待JS引擎的调用,这个时候我们看到的结果是先弹出测试,然后再弹出定时器

    setTimeout我们可以再次定义为:

    在指定时间内, 将任务放入事件队列,等待js引擎空闲后被执行.

    -------------------------讲完原理还不够,定时器的this指向是啥?------------------------- 

        var name = 'my name is window';
        var obj = {
            name: 'my name is obj',
            fn: function () {
                // var that = this; 可以在此处定义一个this,改变this指向
                setTimeout(function () {
                    console.log(this.name);   //my name is window 定时器中this默认指向window
                    console.log(that.name)    //my name is obj 
                }, 1000)
                // 也可以使用箭头函数改变this指向
                // setTimeout(()=> {
                //     console.log(this.name);   //my name is obj
                // }, 1000)
            }    
        }
        obj.fn()

    在setTimeout内部,this绑定采用默认绑定规则,也就是说,在非严格模式下,this会指向window;而在严格模式下,this指向undefined

    学会定时器的原理后,来个小测试~~~~~ 

    for (var i = 0; i < 5; i++) {
    	console.log(i);
    	setTimeout(function timer() {
    		console.log(i);
    	}, i * 1000);
    }  //依次输出:0, 1, 2, 3, 4  接着输出5个5

    稍微解释一下啦:javascript是单线程语言,只有主线程上的所有同步任务执行完毕,主线程才会读取任务队列上的异步任务。for循环属于同步任务,而定时器属于异步任务。所以会在for循环结束之后才开始执行定时器的代码。因此会输出5个5。

    如果帮到你了,请点个赞呦~~~

    展开全文
  • 本文实例讲述了JavaScript高级定时器原理与用法。分享给大家供大家参考,具体如下: setTimeout()和setInterval()可以用来创建定时器,其基本的用法这里就不再做介绍了。这里主要介绍一下javascript的代码队列。在...
  • 【STM32】定时器原理

    2022-06-04 17:15:40
    目录定时器分类:通用定时器特点计数模式的工作原理和区别:1.向上计数模式: 2.向下计数模式: 3.中央对齐模式:通用定时器功能:定时器的工作框架:1.定时器时钟: 2.时基单元:3.输入捕获:4.PWM输出:stm32中有8...
  • 参考文档: 《Cortex -A7 MPCore Technical Reference Manual》 中 Chapter 9:Generic Timer。 《ARM ® Architecture Reference Manual ARMv7...这一章节描述 ARM 通用定时器的实现,ARM 通用定时器实现对于 ARMv7-A.
  • 三种STM32定时器区别
  • 第11章 STC单片机计数器/定时器原理及实现何宾TCON除了用于控制定时器/计数器T0和T1外,同时也可以锁存T0和T1溢出中断源和外部请求中断源等。计数器/
  • 51单片机定时器原理及相关器件

    千次阅读 2022-03-11 16:35:17
    T0 Pin:是单片机一个外部接口(在原理图CPU处可见)。 常用的是SYSclk,定时器会将12M进行分频,看一下上面的图,如果是12T分频就是将12M进行12分频,则输出的频率就是1MHz,1MHz对应的时间周期就是1微秒。即计数...
  • Systick定时器原理及应用 1、什么是Systick定时器? 回答: (1)ystick定时器,是一个简单的定时器,对于CM3,CM4内核芯片,都有Systick定时器。 (2)Systick定时器常用来做延时,或者实时系统的心跳时钟。这样可以...
  • PLC定时器原理及应用PPT课件.pptx
  • STM32高级定时器原理以及输入捕获和输出比较通道原理
  • PLC定时器原理及应用PPT教案.pptx
  • PLC定时器原理及应用学习教案.pptx
  • 555定时器原理及应用(报告)

    万次阅读 多人点赞 2020-06-15 17:26:37
    555定时器简介 1.1 概述 1.2 应用范围 1.3 结构及其工作原理 1.3.1 电路结构 1.3.2 工作原理 二. 555定时器的应用 2.1 555定时器组成施密特触发器 2.1.1 电路结构 2.1.2 工作原理 2.2 555定时器组成单...
  • PLC定时器原理及应用PPT学习教案.pptx
  • STM32 常规定时器原理及常见问题 之培训资料v3.21
  • 单片机的定时器原理及应用PPT学习教案.pptx
  • CC的中断系统和定时器原理PPT学习教案.pptx

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 83,766
精华内容 33,506
关键字:

定时器原理