Java可自定义中断定时器的实现

作者: OneFish | 来源:发表于2016-06-22 10:27 被阅读808次

    Java定时器的实现一般使用的是Timer和ScheduledExecutorService

    • 使用Timer的时候需要自定义一个task继承TimerTask,在task中封装业务逻辑
      然后再使用Timer.scheduleAtFixedRate 按照固定速率执行task中的逻辑

    本文介绍的是ScheduledExecutorService来实现可中断定时器
    我们首先看一下scheduleAtFixedRate 的javaDoc

    • If any execution of the task encounters an exception, subsequent executions are suppressed.Otherwise, the task will only terminate via cancellation or termination of the executor.

    通过javaDoc可以发现需要终止task的方法有三种:

    1. 执行shutdown(),但是这个会终止整个Executor
    2. task抛出异常,在task执行到需要中断的时候,抛出异常
    3. 取消当前执行的task

    执行shutdown()肯定是不合适的,通过主动抛异常的方式来中断也不好
    所以使用取消当前task的方式来实现自定义中断

    1. 首先看一下scheduleAtFixedRate的源码,我们注意到这个方法返回的是ScheduledFuture<?>
    public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit);
    

    ScheduledFuture是继承了Future的

    public interface ScheduledFuture<V> extends Delayed, Future<V>
    

    这样就可以通过Future.cancel()的方式来取消当前task实现自定义中断

    1. 初始化ScheduledExecutorService 线程池
    private ScheduledExecutorService service = Executors.newScheduledThreadPool(20,new NamedThreadFactory("Schedule-Task"));
    
    1. 实现业务逻辑和退出条件
      实现思路是通过保存每个task的Future对象,在满足条件是,执行future.cancel()
    // 当前正在执行的task合集 
    private Map<String,Future> futures = new HashMap<>();
    // 执行定时任务的时间间隔
    private int period = 5;
    private String taskPrefix ="DoSomething-Task";
    public void executeTask(String id) {
    
        // 已有当前定时任务在执行时,删掉当前任务,然后重新启动
        if (futures.containsKey(taskPrefix+id)) {
            futures.get(taskPrefix+id).cancel(true);
            futures.remove(taskPrefix+id);
        }
        Future future = service.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                int currentNum = cacheService.getCurrentShowNum(id);
                // 满足中断task条件
                if ( /* 条件逻辑 */) {
                    Future currentFuture = futures.get(taskPrefix+id);
                    currentFuture.cancel(true);
                    // 任务执行完成
                    futures.remove(taskPrefix+id);
                } else {
                    // 执行task业务逻辑
                }
            }
        },0,period, TimeUnit.MINUTES);
        futures.put(taskPrefix+id,future);
    }
    

    相关文章

      网友评论

      • KEEN0224:我是初学者,这些虽没看懂,但是支持你。
        OneFish:@WUYING 加油↖(^ω^)↗

      本文标题:Java可自定义中断定时器的实现

      本文链接:https://www.haomeiwen.com/subject/mvugdttx.html