ScheduledExecutorService的使用

本文详细介绍ScheduledExecutorService接口,包括其创建方式、主要方法如schedule、scheduleAtFixedRate及scheduleWithFixedDelay等,并提供了示例代码。
摘要由CSDN通过智能技术生成

目录

ScheduledExecutorService 简述

对象创建方式

schedule + Runnable 延迟执行任务

schedule + Callable 延迟执行任务

scheduleAtFixedRate 周期性执行任务

scheduleWithFixedDelay 周期性执行任务


ScheduledExecutorService 简述

1、public interface ScheduledExecutorService extends ExecutorService 延迟或定期执行任务。 

2、schedule 方法使用各种延迟创建任务,并返回一个可用于取消或检查执行的任务对象

3、scheduleAtFixedRate 和 scheduleWithFixedDelay 方法创建并执行某些在取消前一直定期运行的任务

4、所有的 schedule 方法都接受相对延迟和周期作为参数,而不是绝对的时间或日期

5、SheduleExecutorService 是JDK 1.5出来的,比以前的 Timer 性能好

Method  Description
<V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit)

创建并执行在给定延迟后启用的单次操作。

ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit)

创建并执行在给定延迟后启用的单次操作。

ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit)

创建并执行在给定的初始延迟之后,以给定的时间间隔执行周期性动作。即在 initialDelay 初始延迟后,initialDelay+period 执行第一次,initialDelay + 2 * period  执行第二次,依次类推。

ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit)

创建并执行在给定的初始延迟之后首先启用的定期动作,随后上一个执行的终止和下一个执行的开始之间给定的延迟。

对象创建方式

1、此实例最快捷的方式是使用 Executors 工具来创建:

ScheduledExecutorService newScheduledThreadPool(int corePoolSize)创建一个线程池,它可安排在给定延迟后运行任务或者定期地执行任务。 corePoolSize - 池中所保存的线程数,即使线程是空闲的也包括在内。
ScheduledExecutorService newSingleThreadScheduledExecutor()创建一个单线程执行程序,它可安排在给定延迟后运行命令或者定期地执行任务。可保证顺序地执行各个任务,并且在任意给定的时间不会有多个线程是活动的。 同样这是一个无界的任务队列,即虽然线程只有一个,但是新增的任务会在队列中排队等待执行

2、此外除了使用 Executors 创建之外,推荐使用 ScheduledExecutorService 的实现类 ScheduledThreadPoolExecutor

schedule + Runnable 延迟执行任务

1、ScheduledFuture<?> schedule(Runnable command,long delay,TimeUnit unit) :创建并执行在给定延迟后启用的一次性操作。 

2、参数:command - 要执行的任务;delay - 从现在开始延迟执行的时间;unit - 延迟参数的时间单位 


   
   
  1. import java.util.Date;
  2. import java.util.Random;
  3. import java.util.concurrent.Executors;
  4. import java.util.concurrent.ScheduledExecutorService;
  5. import java.util.concurrent.TimeUnit;
  6. /**
  7. * @author wangmaoxiong
  8. * Created by Administrator on 2018/6/28 0028.
  9. * 自定义任务
  10. */
  11. public class MyThread implements Runnable {
  12. private Random random = null;
  13. public MyThread() {
  14. random = new Random();
  15. }
  16. @Override
  17. public void run() {
  18. try {
  19. System.out.println( "任务执行开始:" + new Date());
  20. /**使用随机延时[0-3]秒来模拟执行任务*/
  21. int sleepNumber = random.nextInt(3);
  22. TimeUnit.SECONDS.sleep(sleepNumber);
  23. System.out.println( "任务执行完毕:" + new Date());
  24. } catch (Exception e) {
  25. e.printStackTrace();
  26. }
  27. }
  28. public static void main(String[] args) {
  29. /**使用Executors工具快速构建对象*/
  30. ScheduledExecutorService scheduledExecutorService =
  31. Executors.newScheduledThreadPool(1);
  32. System.out.println( "3秒后开始执行计划线程池服务..." + new Date());
  33. scheduledExecutorService.schedule(new MyThread(), 3, TimeUnit.SECONDS);
  34. }
  35. }

schedule + Callable 延迟执行任务

1、ScheduledFuture<V> schedule(Callable<V> callable, long delay,TimeUnit unit):创建并执行在给定延迟后启用的 一次性操作

2、参数:callable - 要执行的功能;delay - 从现在开始延迟执行的时间;unit - 延迟参数的时间单位 


   
   
  1. import java.util.Date;
  2. import java.util.Random;
  3. import java.util.concurrent.*;
  4. /**
  5. * Created by Administrator on 2018/6/28 0028.
  6. * @author wangmaoxiong
  7. */
  8. public class MyCall implements Callable {
  9. private Random random = null;
  10. public MyCall() {
  11. random = new Random();
  12. }
  13. @Override
  14. public Object call() throws Exception {
  15. try {
  16. String threadName = Thread.currentThread().getName();
  17. System.out.println( "任务执行开始:" + new Date() + ":" + threadName);
  18. /**使用随机延时[0-6]秒来模拟执行任务*/
  19. int sleepNumber = random.nextInt(6);
  20. TimeUnit.SECONDS.sleep(sleepNumber);
  21. System.out.println( "任务执行完毕:" + new Date() + ":" + threadName);
  22. } catch (Exception e) {
  23. e.printStackTrace();
  24. }
  25. return null;
  26. }
  27. public static void main(String[] args) {
  28. /**使用Executors工具快速构建对象*/
  29. ScheduledExecutorService scheduledExecutorService = new ScheduledThreadPoolExecutor(1);
  30. System.out.println( "3秒后开始执行计划线程池服务..." + new Date());
  31. Random random = new Random();
  32. /**计划任务线程池最大个数为2
  33. * 下面开启3个任务,则执行不过来的任务会排队等待执行*/
  34. for (int i = 0; i < 3; i++) {
  35. scheduledExecutorService.schedule(new MyCall(),
  36. random.nextInt(3), TimeUnit.SECONDS);
  37. }
  38. }
  39. }

scheduleAtFixedRate 周期性执行任务

1、ScheduledFuture<?> scheduleAtFixedRate(Runnable command,long initialDelay, long period, TimeUnit unit):创建并执行一个在给定初始延迟后首次启用的定期操作,后续操作具有给定的周期;

2、在 initialDelay 后开始执行,然后在 initialDelay+period 后执行,接着在 initialDelay + 2 * period 后执行,依此类推。意思是下一次执行任务的时间与任务执行过程花费的时间无关,只与period有关!

3、如果此任务的任何一个执行要花费比其周期更长的时间,则将推迟后续执行,但不会同时执行。 

4、如果任务的任何一个执行遇到异常,则后续执行都会被取消。否则,只能通过执行程序的取消或终止方法来终止该任务。

5、参数:command - 要执行的任务;initialDelay - 首次执行的延迟时间;period - 连续执行之间的周期;unit - initialDelay 和 period 参数的时间单位 


   
   
  1. import java.util.Date;
  2. import java.util.Random;
  3. import java.util.concurrent.TimeUnit;
  4. import java.util.concurrent.atomic.AtomicInteger;
  5. /**
  6. * Created by Administrator on 2018/6/28 0028.
  7. * 自定义任务
  8. */
  9. public class MyRunable implements Runnable {
  10. private AtomicInteger atomicInteger = null;
  11. private Random random = null;
  12. public MyRunable() {
  13. atomicInteger = new AtomicInteger(0);
  14. random = new Random();
  15. }
  16. @Override
  17. public void run() {
  18. try {
  19. String threadName = Thread.currentThread().getName();
  20. System.out.println( "1-任务执行开始:" + new Date() + ":" + threadName);
  21. /**使用随机延时[0-3]秒来模拟执行任务*/
  22. int sleepNumber = random.nextInt(5);
  23. TimeUnit.SECONDS.sleep(sleepNumber);
  24. if (atomicInteger.getAndAdd(1) == 3) {
  25. /** 故意抛出一个异常*/
  26. int error = 10 / 0;
  27. }
  28. System.out.println( "2-任务执行完毕:" + new Date() + ":" + threadName);
  29. } catch (Exception e) {
  30. e.printStackTrace();
  31. }
  32. }
  33. }

1)上面 run 方法中如果没有去捕获异常,即没有 try-catch 时,一旦抛出异常却没有捕获到,则后续的定时任务不会再继续执行,这就和 Timer 是一样的,可以参考《Java 定时器Timer与TimeTask》

2)try-catch 时一定要完全捕获到异常,例如果里面抛的是空指针异常,你捕获的却是数组下标越界异常,则仍然会中断计划任务,后续的任务仍然不再执行,所以建议:1)try-catch 包含 run 方法中的所有代码,2)catch 异常最外围使用 "Exception",以免某些异常未捕获而导致计划失败。


   
   
  1. import java.util.Date;
  2. import java.util.Random;
  3. import java.util.concurrent.Executors;
  4. import java.util.concurrent.ScheduledExecutorService;
  5. import java.util.concurrent.TimeUnit;
  6. /**
  7. * Created by Administrator on 2018/6/28 0028.
  8. */
  9. public class Test {
  10. public static void main(String[] args) {
  11. /**使用Executors工具快速构建对象*/
  12. ScheduledExecutorService scheduledExecutorService =
  13. Executors.newSingleThreadScheduledExecutor();
  14. System.out.println( "3秒后开始执行计划线程池服务..." + new Date());
  15. /**每间隔4秒执行一次任务*/
  16. scheduledExecutorService.scheduleAtFixedRate(new MyRunable(),
  17. 3, 4, TimeUnit.SECONDS);
  18. }
  19. }

scheduleWithFixedDelay 周期性执行任务

1、ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay,TimeUnit unit):创建并执行一个在给定初始延迟后首次启用的定期操作,随后,在每一次执行终止和下一次执行开始之间都存在给定的延迟。

2、与 scheduleFixedDelay 区别仅仅在于前后两次任务执行的时间间隔不同而已


   
   
  1. import java.util.Date;
  2. import java.util.Random;
  3. import java.util.concurrent.Executors;
  4. import java.util.concurrent.ScheduledExecutorService;
  5. import java.util.concurrent.TimeUnit;
  6. /**
  7. * Created by Administrator on 2018/6/28 0028.
  8. */
  9. public class Test {
  10. public static void main(String[] args) {
  11. /**使用Executors工具快速构建对象*/
  12. ScheduledExecutorService scheduledExecutorService =
  13. Executors.newSingleThreadScheduledExecutor();
  14. System.out.println( "3秒后开始执行计划线程池服务..." + new Date());
  15. /**每间隔4秒执行一次任务*/
  16. scheduledExecutorService.scheduleWithFixedDelay(new MyRunable(),
  17. 3, 4, TimeUnit.SECONDS);
  18. }
  19. }

在 scheduleFixedDelay 的例子上仅改变上面一行代码,运行结果如下

try-catch 时一定要完全捕获到异常,例如果里面抛的是空指针异常,你捕获的却是数组下标越界异常,则仍然会中断计划任务,后续的任务仍然不再执行,所以建议:1)try-catch 包含 run 方法中的所有代码,2)catch 异常最外围使用 "Exception",以免某些异常未捕获而导致计划失败。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值