面试突击34(如何使用线程池执行定时任务())
在 Java 语言中,有两个线程池可以执行定时任务:ScheduledThreadPool 和 SingleThreadScheduledExecutor,其中 SingleThreadScheduledExecutor 可以看做是 ScheduledThreadPool 的单线程版本,它的用法和 ScheduledThreadPool 是一样的,所以本文重点来看 ScheduledThreadPool 线程池的使用。
ScheduledThreadPool 执行定时任务的方法有以下 3 个:
- 使用 schedule 方法执行定时任务,只执行一次定时任务。
- 使用 scheduleAtFixedRate 方法执行定时任务,执行多次定时任务。
- 使用 scheduleWithFixedDelay 方法执行定时任务,执行多次定时任务。
1.schedule schedule 方法只能执行一次定时任务,它需要传递 3 个参数:
- 第 1 个参数:传递一个任务,Runnable 或 Callable 对象;
- 第 2 个参数:添加定时任务后,再过多久开始执行定时任务;
- 第 3 个参数:时间单位,配合参数 2 一起使用。
import java.time.LocalDateTime;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class ScheduledThreadPoolExample {
public static void main(String[] args) throws InterruptedException {
// 创建 ScheduledThreadPool 线程池
ScheduledExecutorService threadPool = Executors.newScheduledThreadPool(10);
System.out.println("schedule 方法添加任务:" + LocalDateTime.now());
threadPool.schedule(new Runnable() {
@Override
public void run() {
System.out.println("执行 schedule 方法:" + LocalDateTime.now());
}
}, 3, TimeUnit.SECONDS);
// 3s 之后执行// 以下代码是给业务方法一个时间对照信息
TimeUnit.SECONDS.sleep(10);
// 休眠 10s
System.out.println("当前时间:" + LocalDateTime.now());
}
}
以上程序的执行结果如下图所示:
![面试突击34(如何使用线程池执行定时任务())](https://cdn.nlark.com/yuque/0/2022/png/92791/1643285135216-0a5be9dc-bde7-40d8-8d44-7bf2f40da008.png#clientId=ue0197902-a877-4&crop=0&crop=0&crop=1&crop=1&from=paste&<br />
文章图片 <br />
<br> 从上述结果中可以看出,使用 schedule 方法只能执行一次定时任务。<br />
2.scheduleAtFixedRate
scheduleAtFixedRate 方法可以执行多次定时任务,此方法需要 4 个参数:<br />
<ul>
<li>第 1 个参数:传递一个任务,Runnable 或 Callable 对象;</li>
<li>第 2 个参数:添加定时任务后,再过多久开始执行定时任务;</li>
<li>第 3 个参数:定时任务执行的时间间隔;</li>
<li>第 4 个参数:时间单位,配合参数 2 和参数 3 一起使用。</li>
</ul>
下面我们创建一个 3 秒后执行的定时任务,每个定时任务执行的时间间隔为 2 秒,实现代码如下:<br />
<blockquote><code>import java.time.LocalDateTime;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class ScheduledThreadPoolExample {
public static void main(String[] args) throws InterruptedException {
// 创建 ScheduledThreadPool 线程池
ScheduledExecutorService threadPool = Executors.newScheduledThreadPool(10);
System.out.println()
以上程序的执行结果如下图所示:
![面试突击34(如何使用线程池执行定时任务())](https://cdn.nlark.com/yuque/0/2022/png/92791/1643287036829-da0d6744-f637-410a-bd9c-8dd59a5b68e8.png#clientId=u5b0cec9e-c3d0-4&crop=0&crop=0&crop=1&crop=1&from=paste&<br />
文章图片 <br />
<br> 从上述结果可以看出,当任务添加成功之后,3s 后开始执行第一个定时任务,之后每隔 2s 执行一次定时任务。<br />
3.scheduleWithFixedDelay
<strong>【面试突击34(如何使用线程池执行定时任务())】</strong>scheduleWithFixedDelay 方法的使用和 scheduleAtFixedRate 类似,但执行效果完全不同,这个很容易理解如果效果一样就不用创建两个方法了。<br> scheduleWithFixedDelay 方法是在方法执行完成之后,再隔 N 秒执行下一个定时任务,和 scheduleAtFixedRate 的固定时间执行不同,scheduleWithFixedDelay 方法的执行受定时任务执行的时长影响,比如以下代码:<br />
<blockquote><code>import java.time.LocalDateTime;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class ScheduledThreadPoolExample {
public static void main(String[] args) throws InterruptedException {
// 创建 ScheduledThreadPool 线程池
ScheduledExecutorService threadPool = Executors.newScheduledThreadPool(10);
System.out.println()
以上程序的执行结果如下图所示:
![面试突击34(如何使用线程池执行定时任务())](https://cdn.nlark.com/yuque/0/2022/png/92791/1643287771381-5cda78b7-f7c4-41c0-9f25-89c5a7369259.png#clientId=u5b0cec9e-c3d0-4&crop=0&crop=0&crop=1&crop=1&from=paste&<br />
文章图片 <br />
<br> 从上述结果可以看出,定时任务在 3s 之后开始执行,以后每隔 4s 执行一次,这 4s 包含了,定时任务执行花费的 2s,加上每隔 2s 执行一次的时间间隔,也就是说 scheduleWithFixedDelay 是在任务执行完 N 秒之后,再执行下一次定时任务。<br />
总结
线程池执行定时任务的实现方法有 3 个:<br />
<ol>
<li>使用 schedule 方法执行定时任务,只执行一次定时任务。</li>
<li>使用 scheduleAtFixedRate 方法执行定时任务,执行多次定时任务,它的执行时间间隔是固定的,不受定时任务执行时长影响(定时任务时间间隔 > 任务执行时间)。</li>
<li>使用 scheduleWithFixedDelay 方法执行定时任务,执行多次定时任务,它是在定时任务执行完之后,再隔 N 秒开始执行下一次定时任务,它的执行时间受定时任务执行时长影响。</li>
</ol>
<blockquote> 是非审之于己,毁誉听之于人,得失安之于数。<br />
公众号:Java面试真题解析<br />
面试合集:https://gitee.com/mydb/interview<br />
</blockquote></p>
<div class=)
推荐阅读
- 大数据|自动拦截 50% crash,字节自研 Fastbot 如何助力今日头条稳定性测试
- 华为鸿蒙|如何打开华为鸿蒙系统HarmonyOS虚拟器 利用华为DevEco Studio启动华为鸿蒙系统远程虚拟器Remote Virtual Devices
- c#|C#中如何将字符串转换成流,同时如何将流转换成字符串()
- 备战蓝桥杯|【蓝桥python冲刺17天】——如何轻松拿捏必考数论题((第三弹))
- 备战蓝桥杯|【蓝桥python冲刺31天】——如何轻松拿捏必考数论题((第一弹))
- sql|sql 获取两个月内数据_如何在3个月的时间内自学成为数据分析师()
- webpack是如何处理css/less资源的呢
- 其他|如何将本地文件上传到Gitee
- 面试官(来说一说Go语言的函数调用惯例)
- Vue源码学习之响应式是如何实现的