在Java语言中,有两种可以执行定时任务的线程池:ScheduledThreadPool和SingleThreadScheduledExecutor,其中SingleThreadScheduledExecutor可以看作是单线程版的ScheduledThreadPool,其用法和ScheduledThreadPool一样,所以本文重点介绍ScheduledThreadPool线程池的使用。ScheduledThreadPool执行定时任务的方法有3种:使用schedule方法执行定时任务,定时任务只执行一次。使用scheduleAtFixedRate方法执行定时任务,可以执行多个定时任务。使用scheduleWithFixedDelay方法执行定时任务,执行多个定时任务。接下来我们看看这三种方法的具体使用和区别。1、scheduleschedule方法只能执行一次定时任务,需要传递三个参数:第一个参数:传递一个任务,Runnable或Callable对象;第二个参数:添加定时任务后,需要多长时间开始执行定时任务;第三个参数:时间单位,与参数2配合使用。下面我们创建一个3秒后执行的定时任务:{publicstaticvoidmain(String[]args)throwsInterruptedException{//创建ScheduledThreadPool线程池ScheduledExecutorServicethreadPool=Executors.newScheduledThreadPool(10);System.out.println("添加任务的调度方法:"+LocalDateTime.now());threadPool.schedule(newRunnable(){@Overridepublicvoidrun(){System.out.println("执行调度方法:"+LocalDateTime.now());}},3,TimeUnit.SECONDS);//3s然后执行//下面的代码是给业务方法一个时间比较信息TimeUnit.SECONDS.sleep(10);//休眠10sSystem.out.println("Currenttime:"+LocalDateTime.now());}}上面的程序执行结果如下图所示:从上面的结果可以看出,使用schedule方法只能执行一次定时任务。2、scheduleAtFixedRatesscheduleAtFixedRate方法可以执行多个定时任务。该方法需要4个参数:第一个参数:传递一个任务,Runnable或Callable对象;第二个参数:添加定时任务后,需要多长时间开始执行定时任务;第三个参数:定时任务执行的时间间隔;第四个参数:时间单位,与参数2、参数3配合使用。接下来我们创建一个3秒后执行的定时任务,每个定时任务的执行间隔为2秒。实现代码如下:String[]args)throwsInterruptedException{//创建ScheduledThreadPool线程池ScheduledExecutorServicethreadPool=Executors.newScheduledThreadlSystem.printPool(10)("scheduleAtFixedRate方法添加任务:"+LocalDateTime.now());threadPool.scheduleAtFixedRate(newRunnable(){@Overridepublicvoidrun(){System.out.println("ExecutescheduleAtFixedRatemethod:"+LocalDateTime.now());//sleepfor2stry{TimeUnit.SECONDS.sleep(2);}catch(InterruptedExceptione){e.printStackTrace();}}},3L,//3s后开始执行定时任务2L,//定时任务执行间隔为2sTimeUnit.SECONDS);//描述上面两个参数的时间单位}}上面程序的执行结果如下图所示:从上面的结果可以看出,任务添加成功后,第一个定时任务会3s后执行,然后每隔2s执行一个定时任务3.scheduleWithFixedDelayscheduleWithFixedDelay方法的使用和scheduleAtFixedRate类似,但是执行效果完全不同。很容易理解,如果效果一样,就没必要创建两个方法。scheduleWithFixedDelay方法是在方法执行完成后每隔N秒执行下一个定时任务。与scheduleAtFixedRate的定时执行不同,scheduleWithFixedDelay方法的执行受定时任务执行时间的影响。例如下面的代码:importjava.time.LocalDateTime;importjava.util.concurrent.Executors;importjava.util.concurrent.ScheduledExecutorService;importjava.util.concurrent.TimeUnit;publicclassScheduledThreadPoolExample{publicstaticvoidmain(String[]args)throwsInterruptedException{//创建ScheduledThreadPool线程池ScheduledExecutorServicethreadPool=Executors.newScheduledThreadPool(10);System.out.println("scheduleWithFixedDelay方法添加任务:"+LocalDateTime.now());threadPool.scheduleWithFixedDelay(newRunnable(){@Overridepublicvoidrun(){System.out.println("执行scheduleWithFixedDelay方法:"+LocalDateTime.now());//休眠2stry{TimeUnit.SECONDS.sleep(2);}catch(InterruptedExceptione){e.printStackTrace();}}},3L,//3s后开始执行定时任务2L,//定时任务执行完2s后,执行下一个定时任务TimeUnit.SECONDS);//描述上面两个参数的时间单位}}上面程序的执行结果如下图所示:从上面的结果可以看出,定时任务在3s后开始执行,就会执行未来每4秒。这4s包括执行定时任务所花费的2s,加上每2s执行一次的时间间隔。也就是说scheduleWithFixedDelay在任务执行完N秒后执行下一个定时任务。总结线程池执行定时任务有3种实现方式:使用schedule方法执行定时任务,只执行一次定时任务。使用scheduleAtFixedRate方法执行定时任务,执行多个定时任务。它的执行间隔是固定的,不受定时任务执行时长的影响(定时任务的时间间隔>任务执行时间)。使用scheduleWithFixedDelay方法执行定时任务,执行多个定时任务。定时任务执行完后,每隔N秒执行下一个定时任务。它的执行时间受定时任务执行时长的影响。判断是非在自己,名誉在别人,得失在人数。公众号:Java面试真题分析面试合集:https://gitee.com/mydb/interview
