Java定时器选择

article/2025/11/7 2:27:33

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() {@Overridepublic 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() {@Overridepublic 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() {@Overridepublic 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() {@Overridepublic 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://chatgpt.dhexx.cn/article/FHmSjHnR.shtml

相关文章

9.java定时器

java定时器 java的定时器有四种实现方式 使用java的timer类&#xff0c;这种方式可以灵活的控制定时器的开启关闭使用线程和线程池的方法&#xff0c;这种方式对于关闭定时器是不优雅的&#xff0c;甚至可能出错使用spring注解来启动定时任务&#xff0c;使用起来简单&#xff…

Java当中的定时器

目录 一、什么是定时器 二、Java当中的定时器 ①schedule()方法&#xff1a; ②TimerTask ​编辑 ③delay 三、实现一个定时器 前提条件: 代码实现: ①确定一个“任务”&#xff08;MyTask)的描述&#xff1a; ②schedule方法&#xff1a; ③需要一个计时器 属性…

【Java定时器】: Java创建定时器的三种方式(详细讲解)

Java创建定时器的三种方式 第一种&#xff0c;常见的thread&#xff0c;创建一个Thread让他让循环里一直执行&#xff0c;通过 Thread.sleep 来达到 定时任务的效果。 栗子如下&#xff1a; public static void main(String[] args) {final long timeTnterval 1000;Runnable …

Java定时器

目录 一、认识定时器 1、什么是定时器 2、标准库的定时器 二、模拟实现定时器 1、描述定时器中的任务 2、管理多个任务 3、扫描线程 4、优化 5、最终代码 一、认识定时器 1、什么是定时器 定时器是实际开发中常用的一个重要组件&#xff0c;类似于我们生活中的“闹钟…

matlab画图函数之plot【matlab图行绘制一】

plot函数 plot(x,y,’–gs’,‘LineWidth’,2,‘MarkerSize’,10,‘MarkerEdgeColor’,‘b’,‘MarkerFaceColor’,[0.5,0.5,0.5]) plot函数是最基本、最常用的绘图函数&#xff0c;用于绘制线性二维图。有多条曲线时&#xff0c;循环使用由坐标轴颜色顺序属性定义的颜色&…

Matlab画图线型、符号及颜色设置

1. matlab 中线条的主要属性 Color: 颜色LineStyle: 线型LineWidth: 线宽Marker: 标记点的形状MarkerFaceColor: 标记点填充颜色MarkerEdgeColor: 标记点边缘颜色MarkerSize: 标记点大小 2. 各种属性的名称 2.1 线型 -Solid line (default) – Dashed line : Dotted line …

matlab 画图基本

内容安排如下&#xff1a; 1、基本绘制&#xff08;图画大小、图形名称、图画背景、坐标轴名称、刻度范围、曲线颜色、坐标轴字体颜色等&#xff09;2、多条曲线&#xff08;plot hold on&#xff1b;plotyy&#xff1b;subplot&#xff1b;&#xff09;3、日期及时间轴绘图4、…

MATLAB画图详细教程

本文将详细介绍如何用matlab绘图并美化。 关于figure() 创建图窗窗口:figure() figure()的属性: Name:在标题栏显示的名称,接字符串,如Test Position:在电脑屏幕上的位置和大小,后接向量[left,bottom,width,height]也就是说指定了图窗的左下角位置,再向右+width、…

MATLAB画图总结

前言 在进行数据处理展示的时候&#xff0c;为了能直观体现实验的结果&#xff0c;需要进行绘图&#xff0c;让人们能直观的记住数据的走向特征&#xff0c;图像是结果的一种可视化展现&#xff0c;因此掌握一些绘图方法非常重要&#xff0c;使用MATLAB可以很简单的进行画图。下…

matlab 画图基本介绍

1.在命令窗口输入命令时&#xff0c;可以不必每输入一条命令就按enter键执行&#xff0c;可以在输入几行后一同运行。方法是&#xff1a;换行时&#xff0c;只要在按住<shift>键的同时按<enter>键即可&#xff0c;否则matlab就会执行上面输入的所有语句。 2.如何将…

matlab画图操作(修改坐标轴及字体,加粗,颜色修改,适合论文画图)

matlab常用画图操作 1.设置坐标轴2.设置figure大小3.matlab线条设置4.子图设置5.颜色查询6.colorbar设置7.线条透明度设置8.设置坐标轴刻度形式&#xff08;对数刻度&#xff09;9.图例设置10 文件保存11 消除白色边框12 添加子标题13 调换y轴递增顺序 1.设置坐标轴 %设置坐标…

使用matlab画图中图

又到一年论文季&#xff0c;没想到临近投稿的我居然会被图片的清晰度打败&#xff0c;需要子母图的时候&#xff0c;我直接使用powerpoint进行拼接&#xff0c;多次png另存为&#xff0c;图已经糊出了新高度&#xff0c;那种超级糊图在论文里应该是投不出去的吧。。。但是&…

matlab-画图对坐标的显示

前言 许多小朋友对于matlab画图函数再熟悉不过了&#xff0c;但是画图里面还有更细小的地方我们还得注意&#xff0c;对于坐标的显示也是我们在日常生活中常需要我们做的&#xff0c;下面我就将以一个例子1来说明在画图中显示坐标的两种形式。 下面的数据取样格式为 提示&a…

Matlab画图相关知识

目录 一、绘制不同种类的图像 1.1.画一般曲线图 1.2.绘制柱状图 二、matlab的图像处理 2.1将多张图同时绘制在一个Figure上面&#xff0c;采用subplot函数 2.2改变matlab图像坐标刻度增长幅度 2.3设置坐标轴刻度为任意值 2.4在一张Figure中用同一个x对应两个y作图 2.5关于…

MATLAB画图使用不同的线型、点及标记

转载自&#xff1a;MATLAB画图使用不同的线型、点及标记 (baidu.com) 一、 线型、连续标记 先从最普通的说起。在plot函数中指定线型。 tlinspace(0,5,20); x1 t; x2 2*t; x3 3*t; x4 4*t; plot(t,x1,b,t,x2,g-o,t,x3,r*,t,x4,c:d); 这是基础的比较简单的情况。不做…

MATLAB绘图

在MATLAB中绘制函数图形的步骤如下&#xff1a; 先定义变量 x&#xff0c;通过指定的变量 x 值的范围&#xff0c;该函数被绘制&#xff1b; 然后定义函数&#xff0c; y f(x)&#xff1b; 最后调用 plot 命令&#xff0c;如 plot(x, y)。 接下来我们通过例子绘制简单的函…

matlab画图入门教程

**matlab画图&#xff1a;**图像是数据结果的一种可视化表现&#xff0c;它能直观的体现你的数据结果&#xff0c;并且能体现你获得结果的准确性&#xff0c;在当前的大数据时代&#xff0c;在做数据分析的时候&#xff0c;将其可视化可以直观多维的展示数据&#xff0c;可以让…

MATLAB——画图(经典)

plot 二维线图全页折叠 #语法 plot(X,Y) plot(X,Y,LineSpec) plot(X1,Y1,…,Xn,Yn) plot(X1,Y1,LineSpec1,…,Xn,Yn,LineSpecn) plot(Y) plot(Y,LineSpec) plot(___,Name,Value) plot(ax,___) h plot(___) 说明 示例 plot(X,Y) 创建 Y 中数据对 X 中对应值的二维线图。 如果 …

MATLAB 画图

目录 图形对象属性 坐标轴 散点图 Line 属性 imagesc histogram 直方图 subplot 图像保存 其他 图形对象属性 set 设置图形对象属性 set(H,Name,Value)&#xff1a;为 H 标识的对象指定其 Name 属性的值 p plot(1:10); set(p,Color,red)% 更改特定线条的颜色gca 当…

【Matlab】MATLAB绘图

专题四 MATLAB绘图 绘图的目的是使数据可视化。 一 二维曲线 1. 函数plot() 在MATLAB中,函数plot()是最基本的绘图函数,利用它可以绘制出不同的二维曲线。函数plot()的基本用法: plot(x, y) % 其中,x和y分别用于存储x坐标和y坐标数据,通常x和y是长度相等的向…