这篇具有很好参考价值的文章主要介绍了周期性线程池 newScheduledThreadPool。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。
newScheduledThreadPool
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
return new ScheduledThreadPoolExecutor(corePoolSize);
}
public ScheduledThreadPoolExecutor(int corePoolSize) {
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS, new DelayedWorkQueue());
}
ScheduledThreadPoolExecutor继承自ThreadPoolExecutor。它主要用来在给定的延迟 之后运行任务,或者定期执行任务 。ScheduledThreadPoolExecutor的功能与Timer类似,但ScheduledThreadPoolExecutor功能更强大、更灵活。Timer对应的是单个后台线程 ,而ScheduledThreadPoolExecutor可以在构造函数中指定多个 对应的后台线程数。 |
|
Creates a thread pool that can schedule commands to run after a given delay, or to execute periodically. |
|
DelayQueue 是一个无界队列,所以ThreadPoolExecutor的maximumPoolSize 在Scheduled-ThreadPoolExecutor中没有什么意义(设置maximumPoolSize的大小没有什么效果)。 |
ScheduledThreadPoolExecutor 的执行主要分为两大部分。 |
1)当调用ScheduledThreadPoolExecutor的scheduleAtFixedRate() 方法或者scheduleWithFixedDelay() 方法时,会向ScheduledThreadPoolExecutor的DelayQueue 添加一个实现了RunnableScheduledFutur 接口的ScheduledFutureTask 。 |
2)线程池中的线程从DelayQueue中获取ScheduledFutureTask ,然后执行任务。 |
ScheduledThreadPoolExecutor的实现
ScheduledThreadPoolExecutor会把待调度的任务(ScheduledFutureTask )放到一个DelayQueue 中。 |
|
ScheduledFutureTask 主要包含3个成员变量,如下。 |
·long型成员变量time,表示这个任务将要被执行的具体时间 。 |
·long型成员变量sequenceNumber,表示这个任务被添加到ScheduledThreadPoolExecutor中的序号 。 |
·long型成员变量period,表示任务执行的间隔周期 。 |
|
DelayQueue 封装了一个 PriorityQueue ,这个PriorityQueue会对队列中的Scheduled-FutureTask进行排序。排序时,time 小的排在前面(时间早的任务将被先执行)。如果两个ScheduledFutureTask的time相同,就比较sequenceNumber ,sequenceNumber小的排在前面(也就是说,如果两个任务的执行时间相同,那么先提交的任务将被先执行)。 |
|
下图是ScheduledThreadPoolExecutor中的线程1 执行某个周期任务的4个步骤。 |
|
1)线程1从DelayQueue中获取已到期 的ScheduledFutureTask(DelayQueue.take())。到期任务是指ScheduledFutureTask的time大于等于当前时间。 |
2)线程1执行 这个ScheduledFutureTask。 |
3)线程1修改 ScheduledFutureTask的time 变量为下次将要被执行的时间。 |
4)线程1把这个修改time之后的ScheduledFutureTask放回 DelayQueue中(Delay-Queue.add() )。 |
获取任务的过程
获取任务分为3大步骤 |
1)获取Lock。 |
2)获取周期任务。 |
·如果PriorityQueue为空,当前线程到Condition中等待 ;否则执行下面的2.2。 |
·如果PriorityQueue的头元素的time时间比当前时间大,到Condition中等待到time时间 ;否则执行下面的2.3。 |
·获取 PriorityQueue的头元素(2.3.1);如果PriorityQueue不为空,则唤醒 在Condition中等待的所有线程(2.3.2)。 |
3)释放Lock。 |
ScheduledThreadPoolExecutor在一个循环中执行步骤2,直到线程从PriorityQueue获取到一个元素之后(执行2.3.1之后),才会退出无限循环 (结束步骤2)。 |
|
把ScheduledFutureTask放入DelayQueue中的过程
添加任务分为3大步骤。 |
1)获取Lock。 |
2)添加任务。 |
·向PriorityQueue添加任务。 |
·如果在上面2.1中添加 的任务是PriorityQueue的头元素,唤醒 在Condition中等待的所有线程。 |
3)释放Lock。 |
-----------------------------------------------------------------------------读书笔记摘自 书名:Java并发编程的艺术 作者:方腾飞;魏鹏;程晓明文章来源:https://www.toymoban.com/news/detail-453505.html
常见用途
参考:Executor框架的成员文章来源地址https://www.toymoban.com/news/detail-453505.html
线程任务
public class Task implements Runnable {
private final String name;
public Task(String name) {
this.name = name;
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " → " + name + " Start Time = " + new Date());
processCommand();
System.out.println(Thread.currentThread().getName() + " → " + name + " End Time = " + new Date());
}
private void processCommand() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
1. schedule(new Task(), 10, TimeUnit.SECONDS)
public class ScheduledThreadPool {
public static void main(String args[]) throws InterruptedException, ExecutionException {
System.out.println(Thread.currentThread().getName() + "线程: Start at: " + new Date());
ScheduledThreadPoolExecutor exec = (ScheduledThreadPoolExecutor) Executors.newScheduledThreadPool(5);
for (int i = 0; i < 10; i++) {
System.out.println("添加了第" + i + "个线程任务 " + new Date());
exec.schedule(new Task("线程名字" + i), 10, TimeUnit.SECONDS);
}
exec.shutdown();
System.out.println(Thread.currentThread().getName() + "线程: 打卡" + new Date());
while (!exec.isTerminated()) {
}
System.out.println(Thread.currentThread().getName() + "线程: Finished all threads at:" + new Date());
}
}
执行结果分析
执行结果 |
main线程: Start at: Sat May 20 12:51:32 CST 2023 |
添加了第0个线程任务 Sat May 20 12:51:32 CST 2023 |
添加了第1个线程任务 Sat May 20 12:51:32 CST 2023 |
添加了第2个线程任务 Sat May 20 12:51:32 CST 2023 |
添加了第3个线程任务 Sat May 20 12:51:32 CST 2023 |
添加了第4个线程任务 Sat May 20 12:51:32 CST 2023 |
添加了第5个线程任务 Sat May 20 12:51:32 CST 2023 |
添加了第6个线程任务 Sat May 20 12:51:32 CST 2023 |
添加了第7个线程任务 Sat May 20 12:51:32 CST 2023 |
添加了第8个线程任务 Sat May 20 12:51:32 CST 2023 |
添加了第9个线程任务 Sat May 20 12:51:32 CST 2023 |
main线程: 打卡Sat May 20 12:51:32 CST 2023 |
pool-1-thread-5 → 线程名字2 Start Time = Sat May 20 12:51:42 CST 2023 |
pool-1-thread-3 → 线程名字1 Start Time = Sat May 20 12:51:42 CST 2023 |
pool-1-thread-4 → 线程名字3 Start Time = Sat May 20 12:51:42 CST 2023 |
pool-1-thread-2 → 线程名字4 Start Time = Sat May 20 12:51:42 CST 2023 |
pool-1-thread-1 → 线程名字0 Start Time = Sat May 20 12:51:42 CST 2023 |
pool-1-thread-3 → 线程名字1 End Time = Sat May 20 12:51:45 CST 2023 |
pool-1-thread-5 → 线程名字2 End Time = Sat May 20 12:51:45 CST 2023 |
pool-1-thread-3 → 线程名字5 Start Time = Sat May 20 12:51:45 CST 2023 |
pool-1-thread-5 → 线程名字6 Start Time = Sat May 20 12:51:45 CST 2023 |
pool-1-thread-4 → 线程名字3 End Time = Sat May 20 12:51:45 CST 2023 |
pool-1-thread-4 → 线程名字7 Start Time = Sat May 20 12:51:45 CST 2023 |
pool-1-thread-2 → 线程名字4 End Time = Sat May 20 12:51:45 CST 2023 |
pool-1-thread-2 → 线程名字8 Start Time = Sat May 20 12:51:45 CST 2023 |
pool-1-thread-1 → 线程名字0 End Time = Sat May 20 12:51:45 CST 2023 |
pool-1-thread-1 → 线程名字9 Start Time = Sat May 20 12:51:45 CST 2023 |
pool-1-thread-3 → 线程名字5 End Time = Sat May 20 12:51:48 CST 2023 |
pool-1-thread-5 → 线程名字6 End Time = Sat May 20 12:51:48 CST 2023 |
pool-1-thread-4 → 线程名字7 End Time = Sat May 20 12:51:48 CST 2023 |
pool-1-thread-2 → 线程名字8 End Time = Sat May 20 12:51:48 CST 2023 |
pool-1-thread-1 → 线程名字9 End Time = Sat May 20 12:51:48 CST 2023 |
main线程: Finished all threads at:Sat May 20 12:51:48 CST 2023 |
|
从控制台结果可以看出: |
5 个线程去执行10 个线程任务,线程任务放到线程池后延迟10 秒执行 |
scheduleAtFixedRate() |
scheduleWithFixedDelay() |
以固定的 频率 执行 |
以固定的 延时 执行 |
period (周期)指的是两次成功执行之间的时间。 上一个任务开始的时间计时,一个period后,检测上一个任务是否执行完毕, 如果上一个任务执行完毕,则当前任务立即执行, 如果上一个任务没有执行完毕,则需要等上一个任务执行完毕后立即执行。 |
delay (延时)指的是一次执行终止和下一次执行开始之间的延迟。 |
|
|
2. scheduleWithFixedDelay(new Task(), 2, 4, TimeUnit.SECONDS) 初始延时 2s, 固定延时4s
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,
long initialDelay,
long delay,
TimeUnit unit);
参数 |
含义 |
command |
the task to execute |
initialDelay |
the time to delay first execution |
delay |
the delay between the termination of one execution and the commencement of the next |
unit |
the time unit of the initialDelay and delay parameters |
public class FixedDelay {
public static void main(String args[]) throws InterruptedException, ExecutionException {
way1();
way2();
}
private static void way2() {
System.out.println(Thread.currentThread().getName() + "线程: Start at: " + new Date());
ScheduledThreadPoolExecutor scheduledExecutorService = new ScheduledThreadPoolExecutor(1);
scheduledExecutorService.scheduleWithFixedDelay(() -> {
System.out.println(Thread.currentThread().getName() + " → " + " Start Time = " + new Date());
try {
sleep(3000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println(Thread.currentThread().getName() + " → " + " End Time = " + new Date());
}, 1, 4, TimeUnit.SECONDS);
}
private static void way1() {
System.out.println(Thread.currentThread().getName() + "线程: Start at: " + new Date());
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(2);
scheduledExecutorService.scheduleWithFixedDelay(new Task("任务"), 1, 4, TimeUnit.SECONDS);
}
}
执行结果分析
执行结果 |
分析 |
main线程: Start at: Sat May 20 18:54:29 CST 2023 |
|
pool-1-thread-1 → 任务 Start Time = Sat May 20 18:54:30 CST 2023 |
延迟 1 s |
pool-1-thread-1 → 任务 End Time = Sat May 20 18:54:33 CST 2023 |
|
pool-1-thread-1 → 任务 Start Time = Sat May 20 18:54:37 CST 2023 |
等待 4 s 再开始 |
pool-1-thread-1 → 任务 End Time = Sat May 20 18:54:40 CST 2023 |
|
pool-1-thread-1 → 任务 Start Time = Sat May 20 18:54:44 CST 2023 |
等待 4 s 再开始 |
pool-1-thread-1 → 任务 End Time = Sat May 20 18:54:47 CST 2023 |
|
pool-1-thread-1 → 任务 Start Time = Sat May 20 18:54:51 CST 2023 |
等待 4 s 再开始 |
pool-1-thread-1 → 任务 End Time = Sat May 20 18:54:54 CST 2023 |
|
3. scheduleAtFixedRate(new Task(), 1, 4, TimeUnit.SECONDS) 初始延时 1s, 周期4s
执行结果分析
执行结果 |
分析 |
前置条件 |
任务用时 3 秒, period = 4 秒 |
main线程: Starting at: Sat May 20 19:31:13 CST 2023 |
|
pool-1-thread-1 → 任务 Start Time = Sat May 20 19:31:14 CST 2023 |
延时 1 秒 |
pool-1-thread-1 → 任务 End Time = Sat May 20 19:31:17 CST 2023 |
任务用时 3 秒 |
pool-1-thread-1 → 任务 Start Time = Sat May 20 19:31:18 CST 2023 |
period (周期) 4 秒 |
pool-1-thread-1 → 任务 End Time = Sat May 20 19:31:21 CST 2023 |
|
pool-1-thread-1 → 任务 Start Time = Sat May 20 19:31:22 CST 2023 |
|
pool-1-thread-1 → 任务 End Time = Sat May 20 19:31:25 CST 2023 |
|
|
|
任务用时 < period (周期) ,等待时长为:period |
需要等待period 再开始下一个 |
|
|
前置条件 |
任务用时 3 秒, period = 3 秒 |
main线程: Starting at: Sat May 20 19:35:33 CST 2023 |
|
pool-1-thread-1 → 任务 Start Time = Sat May 20 19:35:34 CST 2023 |
|
pool-1-thread-1 → 任务 End Time = Sat May 20 19:35:37 CST 2023 |
|
pool-1-thread-1 → 任务 Start Time = Sat May 20 19:35:37 CST 2023 |
period (周期) 3 秒 |
pool-1-thread-1 → 任务 End Time = Sat May 20 19:35:40 CST 2023 |
|
pool-1-thread-1 → 任务 Start Time = Sat May 20 19:35:40 CST 2023 |
|
pool-1-thread-1 → 任务 End Time = Sat May 20 19:35:43 CST 2023 |
|
pool-1-thread-1 → 任务 Start Time = Sat May 20 19:35:43 CST 2023 |
|
|
|
任务用时 = period (周期) ,等待时长为:period |
需要等待period 再开始下一个 |
|
|
|
|
前置条件 |
任务用时 3 秒, period = 2 秒 |
main线程: Starting at: Sat May 20 19:37:03 CST 2023 |
|
pool-1-thread-1 → 任务 Start Time = Sat May 20 19:37:04 CST 2023 |
|
pool-1-thread-1 → 任务 End Time = Sat May 20 19:37:07 CST 2023 |
|
pool-1-thread-1 → 任务 Start Time = Sat May 20 19:37:07 CST 2023 |
period (周期) 2 秒 无效,以任务用时为准,故结束就开始 |
pool-1-thread-1 → 任务 End Time = Sat May 20 19:37:10 CST 2023 |
|
|
|
任务用时 > period (周期) 4 秒 ,等待时长为:任务用时 |
等任务结束后直接开始执行下一个 |
定时任务☞每天晚上9点执行一次
public class FixedRateDemo {
public static void main(String args[]) throws InterruptedException, ExecutionException, ParseException {
System.out.println(Thread.currentThread().getName() + "线程: Starting at: " + new Date());
ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
long oneDayPeriod = 10000;
long initDelay = getTimeMillis("21:00:00") - getTimeMillis("21:00:03");
initDelay = initDelay > 0 ? initDelay : oneDayPeriod + initDelay;
executor.scheduleAtFixedRate(new Task("定时任务"), initDelay, oneDayPeriod, TimeUnit.MILLISECONDS);
}
private static long getTimeMillis(String time) throws ParseException {
DateFormat dateFormat = new SimpleDateFormat("yy-MM-dd HH:mm:ss");
DateFormat dayFormat = new SimpleDateFormat("yy-MM-dd");
Date curDate = dateFormat.parse(dayFormat.format(new Date()) + " " + time);
return curDate.getTime();
}
}
执行结果分析
执行结果 |
模拟数据 |
分析 |
前置条件:模拟20:59:57 开始执行定时任务,21:00:00 正式执行,周期10 秒 |
|
|
main线程: Starting at: Sat May 20 20:27:54 CST 2023 |
20:59:57 |
开始执行时间 |
pool-1-thread-1 → 定时任务 Start Time = Sat May 20 20:27:57 CST 2023 |
21:00:00 |
当天到9 点开始执行 |
pool-1-thread-1 → 定时任务 End Time = Sat May 20 20:28:00 CST 2023 |
21:00:03 |
任务执行完毕 |
pool-1-thread-1 → 定时任务 Start Time = Sat May 20 20:28:07 CST 2023 |
21:00:00 |
第2 天9 点重新执行 |
pool-1-thread-1 → 定时任务 End Time = Sat May 20 20:28:10 CST 2023 |
|
|
pool-1-thread-1 → 定时任务 Start Time = Sat May 20 20:28:17 CST 2023 |
|
|
pool-1-thread-1 → 定时任务 End Time = Sat May 20 20:28:20 CST 2023 |
|
|
pool-1-thread-1 → 定时任务 Start Time = Sat May 20 20:28:27 CST 2023 |
|
|
pool-1-thread-1 → 定时任务 End Time = Sat May 20 20:28:30 CST 2023 |
|
|
pool-1-thread-1 → 定时任务 Start Time = Sat May 20 20:28:37 CST 2023 |
|
|
|
|
|
|
|
|
前置条件:模拟21:00:03 开始执行定时任务,21:00:00 正式执行,周期10 秒 |
|
|
main线程: Starting at: Sat May 20 20:41:50 CST 2023 |
21:00:03 |
开始执行时间 |
pool-1-thread-1 → 定时任务 Start Time = Sat May 20 20:41:57 CST 2023 |
21:00:00 |
第2 天9 点开始执行 |
pool-1-thread-1 → 定时任务 End Time = Sat May 20 20:42:00 CST 2023 |
21:00:03 |
任务执行完毕 |
pool-1-thread-1 → 定时任务 Start Time = Sat May 20 20:42:07 CST 2023 |
21:00:00 |
第3 天9 点重新执行 |
pool-1-thread-1 → 定时任务 End Time = Sat May 20 20:42:10 CST 2023 |
|
|
pool-1-thread-1 → 定时任务 Start Time = Sat May 20 20:42:17 CST 2023 |
|
|
pool-1-thread-1 → 定时任务 End Time = Sat May 20 20:42:20 CST 2023 |
|
|
pool-1-thread-1 → 定时任务 Start Time = Sat May 20 20:42:27 CST 2023 |
|
|
pool-1-thread-1 → 定时任务 End Time = Sat May 20 20:42:30 CST 2023 |
|
|
到了这里,关于周期性线程池 newScheduledThreadPool的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!