【多线程】定时器,详解定时器原理,让大家更深刻的理解多线程

这篇具有很好参考价值的文章主要介绍了【多线程】定时器,详解定时器原理,让大家更深刻的理解多线程。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言:
大家好,我是良辰丫,今天我们一起了解一下定时器,通过定时器来熟悉一下线程安全等相关知识点.💞💞💞

🧑个人主页:良辰针不戳
📖所属专栏:javaEE初阶
🍎励志语句:生活也许会让我们遍体鳞伤,但最终这些伤口会成为我们一辈子的财富。
💦期待大家三连,关注,点赞,收藏。
💌作者能力有限,可能也会出错,欢迎大家指正。
💞愿与君为伴,共探Java汪洋大海。

【多线程】定时器,详解定时器原理,让大家更深刻的理解多线程

1. 简述定时器

定时器也是软件开发中的一个重要组件. 类似于一个 “闹钟”. 达到一个设定的时间之后, 就执行某个指定好的代码.安排一个任务,不是立即完成,而是在指定时间到达后执行.

定时器常用场景:
定时器是一种实际开发中非常常用的组件. 比如网络通信中, 如果对方 500ms 内没有返回数据, 则断开连接尝试重连. 比如一个 Map, 希望里面的某个 key 在 3s 之后过期(自动删除). 类似于这样的场景就需要用到定时器.

2. java标准库中的定时器

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

public class Test18 {
    public static void main(String[] args) {
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println("hello4");
            }
        }, 4000);
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println("hello3");
            }
        }, 3000);
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println("hello2");
            }
        }, 2000);
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println("hello1");
            }
        }, 1000);
        System.out.println("hello0");
    }
}

【多线程】定时器,详解定时器原理,让大家更深刻的理解多线程

标准库的定时器,其实本质就是Runnable,这个方法的执行是靠Timer内部的线程在时间到了之后执行的.咱们来简单瞧一下源码,有一个延迟时间delay,如果延迟时间小于0,就会抛出异常;反之就会形成定时器,把任务加载到队列中,时间未到,就会阻塞等待,时间到了唤醒任务.

【多线程】定时器,详解定时器原理,让大家更深刻的理解多线程

【多线程】定时器,详解定时器原理,让大家更深刻的理解多线程

3. 自己实现定时器

定时器,内部管理的步数一个任务,可以管理很多任务,我们需要用到一种数据结构,定时器肯定与时间有关,这时,我们想到了堆,优先级队列不就默认是一种小根堆嘛?定时器中,可能多个任务在执行,优先级队列还能保证线程安全.

  • 一个带优先级的阻塞队列.因为阻塞队列中的任务都有各自的执行时刻 (delay). 最先执行的任务一定是 delay 最小的. 使用带优先级的队列就可以高效的把这个 delay 最小的任务找出来.
  • 队列中的每个元素是一个 Task 对象.
  • Task 中带有一个时间属性, 队首元素就是即将要执行的元素.
  • 有一个 worker 线程一直扫描队首元素, 看队首元素是否需要执行.
import java.util.concurrent.PriorityBlockingQueue;
class MyTask2 implements Comparable<MyTask2> {
    public Runnable runnable;
    public long time;
    public MyTask2(Runnable runnable, long delay) {
        this.runnable = runnable;
        this.time = System.currentTimeMillis() + delay;
    }

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

class MyTimer2 {
    private PriorityBlockingQueue<MyTask2> queue = new PriorityBlockingQueue<>();

    // 创建一个锁对象
    private Object locker = new Object();

    // 此处的 delay 是一个形如 3000 这样的数字 (多长时间之后, 执行该任务)
    public void schedule(Runnable runnable, long delay) {
        // 根据参数, 构造 MyTask, 插入队列即可.
        MyTask2 myTask = new MyTask2(runnable, delay);
        queue.put(myTask);
        synchronized (locker) {
            locker.notify();
        }
    }
    // 在这里构造线程, 负责执行具体任务了.
    public MyTimer2() {
        Thread t = new Thread(() -> {
            while (true) {
                try {
                    synchronized (locker) {
                        // 阻塞队列, 只有阻塞的入队列和阻塞的出队列, 没有阻塞的查看队首元素.
                        MyTask2 myTask = queue.take();
                        long curTime = System.currentTimeMillis();
                        if (myTask.time <= curTime) {
                            // 时间到了, 可以执行任务了
                            myTask.runnable.run();
                        } else {
                            // 时间还没到
                            // 把刚才取出的任务, 重新塞回队列中.
                            queue.put(myTask);
                            locker.wait(myTask.time - curTime);
                        }
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        t.start();
    }
}
public class Test17 {
    public static void main(String[] args) {
        // System.out.println(System.currentTimeMillis());
        MyTimer2 myTimer = new MyTimer2();
        myTimer.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello4");
            }
        }, 4000);
        myTimer.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello3");
            }
        }, 3000);
        myTimer.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello2");
            }
        }, 2000);
        myTimer.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello1");
            }
        }, 1000);

        System.out.println("hello0");
    }
}

使用wait来等待处理,而不是使用sleep,wait方便随时提前唤醒.比如目前是早上八点,打算八点半外出,但是八点十分别人又给自己安排了任务,此时线程就被唤醒,要执行某个任务(避免忙等的情况).文章来源地址https://www.toymoban.com/news/detail-428170.html

到了这里,关于【多线程】定时器,详解定时器原理,让大家更深刻的理解多线程的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 多线程案例(3)-定时器

    大家好,我是晓星航。今天为大家带来的是 多线程案例三 相关的讲解!😀 定时器是什么 定时器也是软件开发中的一个重要组件. 类似于一个 “闹钟”. 达到一个设定的时间之后, 就执行某个指定 好的代码. 定时器是一种实际开发中非常常用的组件. 比如网络通信中, 如果对方

    2024年02月14日
    浏览(42)
  • java多线程之定时器

    定时功能在java中主要是通过 Timer 类实现,因为它在内部还是使用多线程的方式进行处理,所以和多线程技术还是有非常大的管理 在JDK库中Timer类主要负责计划任务的功能,也就是在指定时间开始执行某一个任务,Timer类的主要功能就是设置计划任务,封装任务的类确是Timer

    2024年02月05日
    浏览(47)
  • Java多线程案例之定时器

    定时器是一种实际开发中非常常用的组件, 类似于一个 “闹钟”, 达到一个设定的时间之后, 就执行某个指定好的代码. 比如网络通信中, 如果对方 500ms 内没有返回数据, 则断开连接尝试重连. 比如一个 Map, 希望里面的某个 key 在 3s 之后过期(自动删除). 类似于这样的场景就需要

    2024年02月20日
    浏览(49)
  • 【javaEE】阻塞队列、定时器、线程池

    目录 🌴一、阻塞队列 1.概念 2.生产者消费者模型 3.阻塞队列的实现 🏹二、定时器 1.引出定时器 2.定时器的实现 🔥三、线程池 1.引出线程池 2.ThreadPoolExecutor 构造方法 3.标准数据库的4种拒绝策略【经典面试题】【重点掌握】 4.线程池的实现   1.概念 ✨对于队列,首先我们想

    2023年04月21日
    浏览(44)
  • JavaEE & 线程案例 & 定时器 & 线程池 and 工厂模式

    欢迎光临 ^ V ^ 定时器,可以理解为闹钟 我们设立一个时间,时间一到,让一个线程跑起来~ 而Java标准库提供了一个定时器类: Timer ,from java.util 1.1 定时器Timer的使用 1.1.1 核心方法schedule 传入任务引用(TimerTask task)和 “定时”(long delay / ms) 由于TimerTask不是函数式接口,

    2023年04月18日
    浏览(43)
  • 多线程案例 | 单例模式、阻塞队列、定时器、线程池

    单例模式 单例模式是 设计模式 的一种 什么是设计模式? 设计模式好比象棋中的 “棋谱”,红方当头炮,黑方马来跳,针对红方的一些走法,黑方应招的时候有一些固定的套路,按照套路来走局势就不会吃亏,也就发明了一组\\\"棋谱\\\",称为设计模式 软件开发中也有很多常见

    2024年02月15日
    浏览(47)
  • 【JavaEE初阶】多线程(四)阻塞队列 定时器 线程池

    概念 阻塞队列是一种特殊的队列. 也遵守 “ 先进先出 ” 的原则. 阻塞队列能是一种线程安全的数据结构, 并且具有以下特性: 当队列满的时候, 继续入队列就会阻塞, 直到有其他线程从队列中取走元素. 当队列空的时候, 继续出队列也会阻塞,直到有其他线程往队列中插入元素

    2023年04月26日
    浏览(53)
  • 【Java | 多线程案例】定时器的实现

    个人主页:兜里有颗棉花糖 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 兜里有颗棉花糖 原创 收录于专栏【Java系列专栏】【JaveEE学习专栏】 本专栏旨在分享学习JavaEE的一点学习心得,欢迎大家在评论区交流讨论💌 Java中, Timer类 是用于计划和执行重复任务的类( Java标准

    2024年02月03日
    浏览(42)
  • 通俗理解TIM定时器并简单使用

    前言:本文章部分代码参考自野火的例程 本人使用的是野火家的指南者开发板,芯片型号是STM32f103VET6 有纰漏请指出,转载请说明。 学习交流请发邮件 1280253714@qq.com 源代码在这里 B站这位UP主讲51单片机定时器工作原理 讲得很好 stm32有3种定时器,分别是基本定时器、通用定时

    2024年02月10日
    浏览(41)
  • 【Java】多线程案例(单例模式,阻塞队列,定时器,线程池)

    ❤️ Author: 老九 ☕️ 个人博客:老九的CSDN博客 🙏 个人名言:不可控之事 乐观面对 😍 系列专栏: 单例模式是设计模式之一。代码当中的某个类,只能有一个实例,不能有多个。单例模式分为:饿汉模式和懒汉模式 饿汉模式表示很着急,就想吃完饭剩下很多碗,然后一

    2024年02月06日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包