热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

并发编程深入解析:自定义并发类实现周期性任务调度

目录ScheduledThreadPoolExecutor一、主程序二、自定义周期线程池三、自定义周期任务类四、一个被执行的普通任务五、执行结果ScheduledThr

目录

ScheduledThreadPoolExecutor

一、主程序

二、自定义周期线程池

三、自定义周期任务类

四、一个被执行的普通任务

五、执行结果




ScheduledThreadPoolExecutor

周期调度性线程池(Scheduled thread pool)是一个Executor框架的基本线程池的拓展。


  • 延迟任务(Delayed task):在一段时间后执行一次。(可执行Callable和Runnable对象)
  • 周期任务(Periodic task):在一段时间后,永久地周期性地执行。(只能执行Runnable对象)

一、主程序

package xyz.jangle.thread.test.n8_6.schedule;import java.util.Date;
import java.util.concurrent.TimeUnit;/*** 8.6、自定义在周期调度线程池中运行的任务类* @author jangle* @email jangle@jangle.xyz* @time 2020年9月25日 上午9:20:05* */
public class M {public static void main(String[] args) throws Exception {// 使用自定义周期线程池MyScheduledThreadPoolExecutor executor = new MyScheduledThreadPoolExecutor(4);Task task = new Task();System.out.println("Main: " + new Date());executor.schedule(task, 1, TimeUnit.SECONDS);TimeUnit.SECONDS.sleep(6);task = new Task();System.out.println("Main:" + new Date());executor.scheduleAtFixedRate(task, 1, 3, TimeUnit.SECONDS);TimeUnit.SECONDS.sleep(10);executor.shutdown();executor.awaitTermination(1, TimeUnit.DAYS);System.out.println("Main:End of the program.");}}

二、自定义周期线程池

package xyz.jangle.thread.test.n8_6.schedule;import java.util.concurrent.RunnableScheduledFuture;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;/*** 自定义(继承重写)周期调度线程池* @author jangle* @email jangle@jangle.xyz* @time 2020年9月25日 下午3:15:44* */
public class MyScheduledThreadPoolExecutor extends ScheduledThreadPoolExecutor {public MyScheduledThreadPoolExecutor(int corePoolSize) {super(corePoolSize);}@Overrideprotected RunnableScheduledFuture decorateTask(Runnable runnable, RunnableScheduledFuture task) {// 该方法会被 schedule、scheduleAtFixedRate、scheduleWithFixedDelay 方法内部调用// 这个方法的任务是对原任务进行包装。// 包装后的任务必须是实现RunnableScheduledFuture接口的类(因为线程池需要判断是否是周期任务)return new MyScheduledTask(runnable, null, task, this);}@Overridepublic ScheduledFuture scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) {// scheduleAtFixedRate 方法会调用decorateTask方法,所以会返回MyScheduledTask类型的对象ScheduledFuture task = super.scheduleAtFixedRate(command, initialDelay, period, unit);MyScheduledTask myTask = (MyScheduledTask) task;myTask.setPeriod(TimeUnit.MILLISECONDS.convert(period, unit));return myTask;}}

三、自定义周期任务类

在周期调度执行器中执行的任务必须实现RunnableScheduledFuture接口并拓展FutureTask类。

package xyz.jangle.thread.test.n8_6.schedule;import java.util.Date;
import java.util.concurrent.Delayed;
import java.util.concurrent.FutureTask;
import java.util.concurrent.RunnableScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;/*** 自定义在周期调度线程池中运行的任务类* @author jangle* @email jangle@jangle.xyz* @time 2020年9月25日 上午9:22:49* */
public class MyScheduledTask extends FutureTask implements RunnableScheduledFuture {// 原任务private RunnableScheduledFuture task;// 线程池private ScheduledThreadPoolExecutor executor;// 运行周期private long period;// 用于周期任务(开始执行的时间)private long startDate;public MyScheduledTask(Runnable runnable, V result, RunnableScheduledFuture task,ScheduledThreadPoolExecutor executor) {super(runnable, result);this.task = task;this.executor = executor;}@Overridepublic long getDelay(TimeUnit unit) {if (!isPeriodic()) {return task.getDelay(unit);} else {if (startDate == 0) {return task.getDelay(unit);} else {var now = new Date();long delay = startDate - now.getTime();long res = unit.convert(delay, TimeUnit.MILLISECONDS);
// System.out.println("******delay:" + delay + ",res" + res);return res;}}}@Overridepublic int compareTo(Delayed o) {return task.compareTo(o);}@Overridepublic boolean isPeriodic() {return task.isPeriodic();}@Overridepublic void run() {if (isPeriodic() && (!executor.isShutdown())) {var now = new Date();startDate = now.getTime() + period;executor.getQueue().add(this);}System.out.println("MyScheduledTask-Pre:" + new Date());System.out.println("MyScheduledTask: 是否是周期性任务:" + isPeriodic());super.runAndReset();System.out.println("MyScheduledTask-Post:" + new Date());System.out.println("*************************");}public void setPeriod(long period) {this.period = period;}}

四、一个被执行的普通任务

package xyz.jangle.thread.test.n8_6.schedule;import java.util.concurrent.TimeUnit;/*** 普通的任务* @author jangle* @email jangle@jangle.xyz* @time 2020年9月25日 下午4:02:28* */
public class Task implements Runnable {@Overridepublic void run() {System.out.println("Task: Begin.");try {TimeUnit.SECONDS.sleep(2);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("Task: End.");}}

五、执行结果

Main: Sat Oct 03 09:23:16 CST 2020
MyScheduledTask-Pre:Sat Oct 03 09:23:17 CST 2020
MyScheduledTask: 是否是周期性任务:false
Task: Begin.
Task: End.
MyScheduledTask-Post:Sat Oct 03 09:23:19 CST 2020
*************************
Main:Sat Oct 03 09:23:22 CST 2020
MyScheduledTask-Pre:Sat Oct 03 09:23:23 CST 2020
MyScheduledTask: 是否是周期性任务:true
Task: Begin.
Task: End.
MyScheduledTask-Post:Sat Oct 03 09:23:25 CST 2020
*************************
MyScheduledTask-Pre:Sat Oct 03 09:23:26 CST 2020
MyScheduledTask: 是否是周期性任务:true
Task: Begin.
Task: End.
MyScheduledTask-Post:Sat Oct 03 09:23:28 CST 2020
*************************
MyScheduledTask-Pre:Sat Oct 03 09:23:29 CST 2020
MyScheduledTask: 是否是周期性任务:true
Task: Begin.
Task: End.
MyScheduledTask-Post:Sat Oct 03 09:23:31 CST 2020
*************************
Main:End of the program.

 


推荐阅读
author-avatar
shadow
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有