作者:shadow | 来源:互联网 | 2024-10-23 15:55
目录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.