Java定时器选择

news2024/11/27 13:45:49

java计时器和死循环哪个好?哪个建议使用?

  1. 计时器性能更好,但是写起来稍微复杂一点。如果是非常短暂的延迟,用死循环也未尝不可。
  2. 一般来说能不用死循环的尽量不用死循环!
  3. 如果你使用的是JDK1.5以上的,可以使用ScheduledThreadPoolExecutor来完成Timer的功能,这个实现起来简单,而且相比timer的缺陷进行了弥补。
  4. 那就看你程序对时间的要求高不高,循环内处理时间长不长了。用死循环的话,它执行的时间不是固定的(每次执行完一次任务时间+睡眠时间)用计时器的话,它是每隔固定时间执行一次。



死循环实现定时器

//死循环方式, 无法保证一直执行, 曾经在Spring Boot上使用这种方式执行定时任务, 运行两个月后不知道哪天这个任务
//所在的线程不执行了, 这条线程的所有异常都catch了, 没有往外抛.
whiletrue{
    Thread.sleep(time);
    code;
}



Timer

Timer类提供了一个核心接口,schedule(安排) 指定一个任务交给定时器,在一定时间之后再去执行这个任务~

使用Timer和TimerTask存在一些缺陷:

1.Timer只创建了一个线程。当你的任务执行的时间超过设置的延时时间将会产生一些问题。
2.Timer创建的线程没有处理异常,因此一旦抛出非受检异常,该线程会立即终止。
JDK 5.0以后推荐使用ScheduledThreadPoolExecutor。该类属于Executor Framework,它除了能处理异常外,还可以创建多个线程解决上面的问题。

//Timer和TimerTask的使用
Timer  timer = new Timer();
timer.schedule(new TimerTask() {
    @Override
    public void run() {
        log.e("time:");
    }
}, 2000, 40);//2000表示第一次执行任务延迟时间,40表示以后每隔多长时间执行一次run里面的任务

//取消定时器
timer.cancel();



ScheduledThreadPoolExecutor (强烈建议使用)

ScheduledThreadPoolExecutor,它可另行安排在给定的延迟后运行命令,或者定期执行命令。需要多个辅助线程时,或者要求 ThreadPoolExecutor 具有额外的灵活性或功能时,此类要优于Timer。

参考:
https://blog.csdn.net/cristianoxm/article/details/107640772
https://blog.csdn.net/wenzhi20102321/article/details/78681379

注意:

如果ScheduledThreadPoolExecutor中执行的任务出错抛出异常后,不仅不会打印异常堆栈信息,同时还会取消后面的调度。
https://blog.csdn.net/m0_71777195/article/details/127441811

//ScheduledThreadPoolExecutor的简单使用, 这里先学会简单使用再深入探讨。
//corePoolSize – 保留在池中的线程数,即使它们处于空闲状态,除非设置allowCoreThreadTimeOut
ScheduledThreadPoolExecutor  scheduled = new ScheduledThreadPoolExecutor(2);
//固定频率周期任务scheduleAtFixedRate, 除了这个类型的还有三种类型任务.
scheduled.scheduleAtFixedRate(new Runnable() {
    @Override
    public void run() {
        System.out.println(LocalDateTime.now());
        try {
             Thread.sleep(8000);
        } catch (Exception e) {
            //TODO 不要往外面抛异常, ScheduledThreadPoolExecutor中执行的任务出错抛出异常后,不仅不会打印异常堆栈信息,同时还会取消后面的调度.
             e.printStackTrace();
        }
    }
}, 0, 40, TimeUnit.MILLISECONDS);
//0表示首次执行任务的延迟时间,40表示每次执行任务的间隔时间,TimeUnit.MILLISECONDS执行的时间间隔数值单位
//间隔单位毫秒:TimeUnit.MILLISECONDS
//间隔单位秒:TimeUnit.SECONDS
//间隔单位分钟:TimeUnit.MINUTES
//间隔单位小时:TimeUnit.HOURS
//间隔单位天:TimeUnit.DAYS

//输出结果:
2022-11-29T21:54:22.090508100
2022-11-29T21:54:30.096814100
2022-11-29T21:54:38.102857400
2022-11-29T21:54:46.105952300

//这个方法的作用是周期性的调度task执行。task第一次执行的延迟根据initialDelay参数确定,以后每一次执行都间隔period时长。
//如果task的执行时间大于定义的period,那么下一个线程将在当前线程完成之后再执行。整个调度保证不会出现一个以上任务同时执行。

//尝试停止所有正在执行的任务,停止等待任务的处理,并返回等待执行的任务列表。从此方法返回后,这些任务将从任务队列中排出(删除)。
//此方法不等待主动执行的任务终止。使用awaitTermination来做到这一点。
//除了尽最大努力停止处理正在执行的任务之外,没有任何保证。此实现通过Thread.interrupt中断任务;任何未能响应中断的任务可能永远不会终止。
scheduled.shutdownNow();

ScheduledThreadPoolExecutor 结构概述

在这里插入图片描述

ScheduledExecutorService接口介绍

ScheduledThreadPoolExecutor直接继承自ScheduledExecutorServiceScheduledThreadPoolExecutor 类的功能也主要体现在ScheduledExecutorService 接口上,它的最主要的功能就是可以对其中的任务进行调度,比如延迟执行、定时执行等等。
ScheduledExecutorService接口定义:

public interface ScheduledExecutorService extends ExecutorService {
    //提交在给定延迟后启用的一次性任务(无返回值)。
    public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit);
    
    //提交在给定延迟后启用带返回值的一次性任务。
    public <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit);
    
    //固定频率周期任务
    public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit);
    
    //固定延迟周期任务
    public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit);
}
从上面接口定义我们知道,提供了四个方法,下面我们就分别介绍:
  1. schedule (Runnable task, long delay, TimeUnit timeunit) -> 一次性任务(无返回值)
    这个方法的意思是在指定延迟之后运行task。这个方法有个问题,就是没有办法获知task的执行结果。如果我们想获得task的执行结果,我们可以传入一个Callable的实例.
//创建一个线程池,可以安排命令在给定的延迟后运行,或定期执行
//corePoolSize保留在池中的线程数,即使它们处于空闲状态
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5);
ScheduledFuture scheduledFuture =
scheduledExecutorService.schedule(new Runnable() {
         @Override
        public void run() {
	        System.out.println("Executed!");
        }
     },5,TimeUnit.SECONDS);
//有序关闭之前提交的任务,但不会接受新的任务。如果已经关闭,调用没有额外的效果。
//此方法不等待先前提交的任务执行完成, 如果要等待任务执行完成后再关闭使用awaitTermination方法.
scheduledExecutorService.shutdown();

  1. schedule (Callable task, long delay, TimeUnit timeunit) -> 一次性任务(有返回值)
    这个方法与schedule (Runnable task)类似,也是在指定延迟之后运行task,不过它接收的是一个Callable实例,此方法会返回一个ScheduleFuture对象,通过ScheduleFuture我们可以取消一个未执行的task,也可以获得这个task的执行结果。
//创建一个线程池,可以安排命令在给定的延迟后运行,或定期执行
//corePoolSize保留在池中的线程数,即使它们处于空闲状态
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5);
ScheduledFuture scheduledFuture =
scheduledExecutorService.schedule(new Callable() {
    public Object call() {
        System.out.println("Executed!");
        return "Called!";
    }
},5,TimeUnit.SECONDS);
System.out.println("result = " + scheduledFuture.get());
//有序关闭之前提交的任务,但不会接受新的任务。如果已经关闭,调用没有额外的效果。
//此方法不等待先前提交的任务执行完成, 如果要等待任务执行完成后再关闭使用awaitTermination方法.
scheduledExecutorService.shutdown();
  1. scheduleAtFixedRate (Runnable, long initialDelay, long period,TimeUnit timeunit) -> 周期性任务
    这个方法的作用是周期性的调度task执行。task第一次执行的延迟根据initialDelay参数确定,以后每一次执行都间隔period时长。
    如果task的执行时间大于定义的period,那么下一个线程将在当前线程完成之后再执行。整个调度保证不会出现一个以上任务同时执行。
//corePoolSize – 保留在池中的线程数,即使它们处于空闲状态,除非设置allowCoreThreadTimeOut
ScheduledThreadPoolExecutor  scheduled = new ScheduledThreadPoolExecutor(2);
//固定频率周期任务scheduleAtFixedRate, 除了这个类型的还有三种类型任务.
scheduled.scheduleAtFixedRate(new Runnable() {
    @Override
    public void run() {
        System.out.println(LocalDateTime.now());
        try {
             Thread.sleep(8000);
        } catch (Exception e) {
            //TODO 不要往外面抛异常, ScheduledThreadPoolExecutor中执行的任务出错抛出异常后,不仅不会打印异常堆栈信息,同时还会取消后面的调度.
             e.printStackTrace();
        }
    }
}, 0, 40, TimeUnit.MILLISECONDS);
//0表示首次执行任务的延迟时间,40表示每次执行任务的间隔时间,TimeUnit.MILLISECONDS执行的时间间隔数值单位
//间隔单位毫秒:TimeUnit.MILLISECONDS
//间隔单位秒:TimeUnit.SECONDS
//间隔单位分钟:TimeUnit.MINUTES
//间隔单位小时:TimeUnit.HOURS
//间隔单位天:TimeUnit.DAYS

//输出结果:
2022-11-29T21:54:22.090508100
2022-11-29T21:54:30.096814100
2022-11-29T21:54:38.102857400
2022-11-29T21:54:46.105952300

//尝试停止所有正在执行的任务,停止等待任务的处理,并返回等待执行的任务列表。从此方法返回后,这些任务将从任务队列中排出(删除)。
//此方法不等待主动执行的任务终止。使用awaitTermination来做到这一点。
//除了尽最大努力停止处理正在执行的任务之外,没有任何保证。此实现通过Thread.interrupt中断任务;任何未能响应中断的任务可能永远不会终止。
scheduled.shutdownNow();
  1. scheduleWithFixedDelay (Runnable, long initialDelay, long period, TimeUnit timeunit) -> 周期性任务
    scheduleWithFixedDelay的参数和scheduleAtFixedRate参数完全一致,它们的不同之处在于对period调度周期的解释。在scheduleAtFixedRate中,period指的两个任务开始执行的时间间隔,也就是当前任务的开始执行时间和下个任务的开始执行时间之间的间隔。而在scheduleWithFixedDelay中,period指的当前任务的结束执行时间到下个任务的开始执行时间。

ScheduledExecutorService的关闭

和ExecutorService类似, 我们在使用完ScheduledExecutorService时需要关闭它。如果不关闭的话,JVM会一直运行直,即使所有线程已经关闭了。关闭ScheduledExecutorService可以使用其继承自ExecutorService接口的shutdown()和shutdownNow()方法,两者的区别请参考【Java线程池 ExecutorService】。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/47845.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PyQt5可视化编程-控件

控件就像是应用这座房子的一块块砖。PyQt5有很多的控件&#xff0c;比如按钮&#xff0c;单选框&#xff0c;滑动条&#xff0c;复选框等等。我们将介绍一些很有用的控件&#xff1a; QCheckBox,ToggleButton,QSlider,QProgressBar, QCalendarWidget,QPixmap,QLineEdit,QSplitt…

实验四+ R型指令设计实验【计算机组成原理】

实验四+ R型指令设计实验【计算机组成原理】 前言推荐实验四+ R型指令设计实验结果附录defineInstMemIDEX最后前言 编写于 2022/11/22 VIP发布于 2022/11/22 实验于 2022/11/24 发布于 2022/11/24 以下内容源自计算机组成原理实验 仅供学习交流使用 推荐 实验四+ R型指令…

论文指标评价体系及权重计算

一 、评价指标体系 评价指标体系构建在实际研究中使用较为广泛&#xff0c;比如企业绩效评价指标体系构建、政府财政支出绩效评价、医院绩效评价研究等等。 ‍1、相关背景 在中国知网搜索 “ 评价指标 ”、“ 指标体系权重 ” 等相关关键词&#xff0c;可以发现&#xff0c;…

学习ASP.NET Core Blazor编程系列十三——路由(完)

九、NavigationManager 有的时候我们可能需要在代码里进行导航&#xff0c;如果是JavaScript我们会用window.location来切换页面&#xff0c;Blazor为我们提供了相应的封装&#xff1a;NavigationManager。使用NavigationManager可以通过代码直接进行页面间的跳转。我们在BookI…

算法训练Day34 贪心算法专题 | LeetCode1005.K次取反后最大化的数组和 ;134.加油站;135.分发糖果(不要两头兼顾,一边一边处理)

前言&#xff1a; 算法训练系列是做《代码随想录》一刷&#xff0c;个人的学习笔记和详细的解题思路&#xff0c;总共会有60篇博客来记录&#xff0c;计划用60天的时间刷完。 内容包括了面试常见的10类题目&#xff0c;分别是&#xff1a;数组&#xff0c;链表&#xff0c;哈…

基于人工势场法的移动机器人路径规划研究(Matlab代码实现)

目录 &#x1f4a5;1 概述 &#x1f4da;2 运行结果 &#x1f389;3 参考文献 &#x1f468;‍&#x1f4bb;4 Matlab代码 &#x1f4a5;1 概述 路径规划是移动机器人领域的热点研究方向&#xff0c;人工势场法已在工业机器人路径规划中得到广泛应用&#xff0c;近年来正逐…

RKMEDIA--VI的使用

在上一篇文章RKMEDIA使用简介中简单的介绍了rkmedia的组成部分&#xff0c;本章主要聊聊VI模块。 rkmedia中的VI模块主要可以从两个方式获取流&#xff1a;直接打开video节点的方式、使用rk平台的rkaiq。 1、直接打开video节点的方式 顾名思义只需要在vi初始化中配置VI_CHN_AT…

Redeis缓存查询基于元注解与AOP结合使用——不过时的优雅

Redeis缓存查询基于元注解与AOP结合使用 根据优化需要&#xff0c;数据查询的时候无法避免的使用Redis基于缓存查询&#xff0c;进而减少对于数据库的查询压力&#xff0c;对于过多的方法基于缓存存储&#xff0c;为提高代码的复用性&#xff0c;采用一种不过时的写法。 整体的…

spring JPA整合hibernate,IDEA社区版,Java

spring JPA整合hibernate&#xff0c;IDEA社区版&#xff0c;Java 本文基于IDEA社区版&#xff0c;不是IDEA企业版。 &#xff08;1&#xff09;首先用IDEA新建一个spring web项目。参考文章&#xff1a; IDEA社区版(Community Edition)创建Springboot-Web项目&#xff0c;J…

第十二章 使用 Monorepo 方式管理组件生态

组件库一般都会配有周边产品&#xff0c;比如 Admin 、Template、CLI 工具等等。周边产品相当于有关联的多个项目&#xff0c;更准确的说法是多个软件包。这个时候就应该使用 Monorepo 方式组织代码&#xff0c;方便频繁在多个项目间同时交替开发&#xff0c;同时发布&#xff…

图解LeetCode——895. 最大频率栈(难度:困难)

一、题目 设计一个类似堆栈的数据结构&#xff0c;将元素推入堆栈&#xff0c;并从堆栈中弹出 出现频率 最高的元素。 实现 FreqStack 类: FreqStack() 构造一个空的堆栈。void push(int val) 将一个整数 val 压入栈顶。int pop() 删除并返回堆栈中出现频率最高的元素。如果出…

圣杯与双飞翼布局,clip-path,列表与生成元素,计数器

❤️ Author&#xff1a; 老九 ☕️ 个人博客&#xff1a;老九的CSDN博客 &#x1f64f; 个人名言&#xff1a;不可控之事 乐观面对 &#x1f60d; 系列专栏&#xff1a; 文章目录圣杯与双飞翼布局clip属性clip-path属性例子&#xff08;不同区域使用不同颜色的导航&#xff09…

【MySQL 18】Docker 安装 MySQL8 .0.30

1、查看可用的 MySQL 版本 访问 MySQL 镜像库地址&#xff1a; https://hub.docker.com/_/mysql?tabtags 。2、拉取 MySQL 8.0.30 镜像 拉取官方的指定版本的镜像&#xff1a; docker pull mysql:8.0.30[rootlocalhost deploy]# docker pull mysql:8.0.30 8.0.30: Pulling…

Gly-Gly-Arg, 54944-27-3/55033-48-2

贻贝信息素的模拟物&#xff0c;诱导各种贻贝物种的聚集&#xff0c;如绒螯虾。GGR还能刺激浮游生物幼虫定居。 编号: 401458中文名称: Gly-Gly-Arg英文名: Gly-Gly-ArgCAS号: 54944-27-3/55033-48-2单字母: H2N-GGR-OH三字母: H2N-Gly-Gly-Arg-COOH氨基酸个数: 3分子式: C10H2…

【C语言初阶(NEW)】五、操作符详解(二)|隐式类型转换|算术转换|操作符的属性

目录 一、表达式求值 1.1 隐式类型转换 1.1.1 什么是整型提升&#xff08;整型提升&#xff09; 1.1.2 整型提升的意义 1.1.3 有符号&#xff08;signed&#xff09;与无符号&#xff08;unsigned&#xff09;的区别 1.1.4 有符号&#xff08;signed&#xff09;类型的整…

Redis学习笔记②实战篇_黑马点评项目

若文章内容或图片失效&#xff0c;请留言反馈。部分素材来自网络&#xff0c;若不小心影响到您的利益&#xff0c;请联系博主删除。 资料链接&#xff1a;https://pan.baidu.com/s/1189u6u4icQYHg_9_7ovWmA&#xff08;提取码&#xff1a;eh11&#xff09;在线视频&#xff1a;…

知道创宇ScanA免费试用|守护网络空间内容安全生命线

《淮南子说山训》中有言&#xff0c;“众曲不容直&#xff0c;众枉不容正&#xff0c;故……众议成林&#xff0c;无翼而飞&#xff0c;三人成市虎”。随着互联网社交、即时通讯工具等社交媒体的蓬勃发展&#xff0c;大众发布、传播和获取信息的方式更加简便、渠道更为广泛。也…

安科瑞 ARCM300-Z-4G 导轨式智慧用电监控装置 猪舍无线火灾探测器

安科瑞 王晶淼/刘芳 1 概述 智慧用电在线监控装置是针对 0.4kV 以下的 TT、TN 系统设计的智能电力装置&#xff0c;具有单、三相交流电测量、四象限电能计量、谐波分析、遥信输入、遥信输出功能&#xff0c;以及 RS485 通讯或 GPRS 无线通讯功能&#xff0c;通过对配电回路的剩…

YOLO V5 详解

YOLO V5 Backbone SPPF SPP 是使用了3个kernel size不一样大的pooling 并行运算。SPPF是将kernel size为5的 pooling 串行运算&#xff0c;这样的运算的效果和SPP相同&#xff0c;但是运算速度加快。因为SPPF减少了重复的运算&#xff0c;每一次的pooling 运算都是在上一次运…

IP-guard产品相关端口和服务名称

数据库 SQL Server (SQLEXPRESS) 服务器 OCULAR V3 SERVER 中继器 OCULAR V3 MIDTIER SERVER 客户端 WINDOWS HELPER SERVICE 报表 OCULAR V3 REPORT SERVER web服务器 Ocular web server,OCULAR Console Web Service 云备份服务器 OCULAR File Cloud Backup Server,OCULAR Fil…