感谢学java的生生提供的视频,让我能够速成部分实践八股,弥补了我没有好好看和学习国外CS课程的缺憾
现在有一个Main函数,我们要实现里面scheduleService方法(就是实现@Schedule注解),让main函数正常实习
package tech.insight;
/**
* @author gongxuanzhangmeit@gmail.com
*/
public class Main {
public static void main(String[] args) throws InterruptedException {
ScheduleService scheduleService = new ScheduleService();
scheduleService.schedule(() -> {
System.out.println(1);
}, 1000);
Thread.sleep(1000);
System.out.println("添加一个每200毫秒打印一个2的定时任务");
scheduleService.schedule(() -> {
System.out.println(2);
}, 200);
}
}
package tech.insight;
/**
* @author gongxuanzhangmelt@gmail.com
*/
public class ScheduleService {
void schedule(Runnable task, long delay) {
// TODO
}
}
这是一个新的工程。我们创建了一个类,这个类有一个函数 `schedule`,它有两个参数:第一个是一个任务(task),第二个是一个延迟时间(delay),单位是毫秒。每隔这么多毫秒,我们会让这个任务自动执行一次。一般来说这里可以加一个 `TimeUnit`,但我们默认使用毫秒。
我们可以先写一个“慢函数”,这个慢函数直接调用某个方法,比如打印一个“1”。我们希望它每隔100毫秒打印一次“1”。当然,在主函数中,我们不能阻塞主线程。因此,我们在主函数里先睡眠一秒,然后添加一个每200毫秒打印一次“2”的定时任务。也就是说,我们在一秒之后,再添加一个每200毫秒打印“2”的任务。
接下来我们要实现 `schedule` 方法,使得这个“慢函数”能够正常运行。
首先思考一个问题:这个任务是由谁来执行的?我们可以随便定义一个线程池,无所谓。问题是,如何用线程池去执行一个带延迟的任务? 最直观的想法就是新建一个线程池线程,让他按照要求sleep那么几秒,但是有问题:下一次什么时候能执行?目前这个任务只能执行一次,也没有延迟。我们能不能简单粗暴地让线程先 `sleep(delay)` 毫秒,然后直接调用 `task.run()`?其实是可以的,但这会带来几个问题。
void schedule(Runnable task, long delay) {
ExecutorService executorService = Executors.newFixedThreadPool(6);
executorService.execute(() -> {
Thread.sleep(delay);
task.run();
});
}
第一个问题是:下一次什么时候执行?我们可以写一个死循环,在任务执行完后再次睡眠 `delay` 时间,然后继续执行。但这样又引出另一个问题:如果我们使用的线程池只有六个线程,那么最多只能同时处理六个任务。当用户第七次调用 `schedule` 时,线程池就会耗尽,无法提交新任务,显然这不符合我们的需求。
所以我们需要一个更好的设计思路。设想有一个组件,它可以在指定的时间点自动把任务提交到线程池中,而不是在调用 `schedule` 的时候立即提交。换句话说,如果有一个组件叫“触发器”(Trigger),它负责等待合适的时间,然后把任务

最低0.47元/天 解锁文章
509

被折叠的 条评论
为什么被折叠?



