Java - ScheduledExecutorService 101

Executors.newScheduledThreadPool

实际返回类型:

    /**
     * Creates a thread pool that can schedule commands to run after a
     * given delay, or to execute periodically.
     * @param corePoolSize the number of threads to keep in the pool,
     * even if they are idle
     * @return a newly created scheduled thread pool
     * @throws IllegalArgumentException if {@code corePoolSize < 0}
     */
    public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
        return new ScheduledThreadPoolExecutor(corePoolSize);
    }

    /**
     * Creates a thread pool that can schedule commands to run after a
     * given delay, or to execute periodically.
     * @param corePoolSize the number of threads to keep in the pool,
     * even if they are idle
     * @param threadFactory the factory to use when the executor
     * creates a new thread
     * @return a newly created scheduled thread pool
     * @throws IllegalArgumentException if {@code corePoolSize < 0}
     * @throws NullPointerException if threadFactory is null
     */
    public static ScheduledExecutorService newScheduledThreadPool(
            int corePoolSize, ThreadFactory threadFactory) {
        return new ScheduledThreadPoolExecutor(corePoolSize, threadFactory);
    }

实例

scheduleAtFixedRate方法:

  • initialDelay设置方法第一次执行前的延时时间, 设置为0即马上就执行.
  • period用于控制后续的重复执行.
    该方法的计时从前一次执行的开始计时. 比如说第一次执行是在第1秒, period1秒, 那么第二次执行将会在第2秒开始, 第3次执行将会在第3秒开始... 如果出现某次任务的执行时长超过period, 那么需要等待这次执行完成才会开始下一次.
    即该方法的下一次执行时间为max(上一次执行需要花的时间, period).
  • 如果某次执行过程中抛出了exception, 那么后续的执行将不会再继续了.
    /**
     * Creates and executes a periodic action that becomes enabled first
     * after the given initial delay, and subsequently with the given
     * period; that is executions will commence after
     * {@code initialDelay} then {@code initialDelay+period}, then
     * {@code initialDelay + 2 * period}, and so on.
     * 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.  If any execution of this task
     * takes longer than its period, then subsequent executions
     * may start late, but will not concurrently execute.
     *
     * @param command the task to execute
     * @param initialDelay the time to delay first execution
     * @param period the period between successive executions
     * @param unit the time unit of the initialDelay and period parameters
     * @return a ScheduledFuture representing pending completion of
     *         the task, and whose {@code get()} method will throw an
     *         exception upon cancellation
     * @throws RejectedExecutionException if the task cannot be
     *         scheduled for execution
     * @throws NullPointerException if command is null
     * @throws IllegalArgumentException if period less than or equal to zero
     */
    public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
                                                  long initialDelay,
                                                  long period,
                                                  TimeUnit unit);

实例:

    public static void testScheduleAtFixedRate(){
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                try {
                    System.out.println("working at: " + getCurrentTime());
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                }
            }
        };
        ScheduledFuture<?> future = scheduledExecutorService.scheduleAtFixedRate(runnable, 0, 1000, TimeUnit.MILLISECONDS);
        Thread main = Thread.currentThread();
        scheduledExecutorService.schedule(()-> main.interrupt(), 5000, TimeUnit.MILLISECONDS);
        try {
            future.get();
        } catch (InterruptedException | ExecutionException e) {
            future.cancel(true);
        }

    }

输出:

working at: 23:07:17
working at: 23:07:19
working at: 23:07:21

从输出可以看出, 第一次执行开始于23:07:17, 按照period参数1000, 第二次执行应该是在23:07:18, 但是实际是在23:07:19, 因为任务执行一次需要2000毫秒, 所以即使period计时满足了, 仍然要等待前一次执行完成, 才会执行下一次.

scheduleWithFixedDelay方法

注释:

    /**
     * Creates and executes a periodic action that becomes enabled first
     * after the given initial delay, and subsequently with the
     * given delay between the termination of one execution and the
     * commencement of the next.  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.
     *
     * @param command the task to execute
     * @param initialDelay the time to delay first execution
     * @param delay the delay between the termination of one
     * execution and the commencement of the next
     * @param unit the time unit of the initialDelay and delay parameters
     * @return a ScheduledFuture representing pending completion of
     *         the task, and whose {@code get()} method will throw an
     *         exception upon cancellation
     * @throws RejectedExecutionException if the task cannot be
     *         scheduled for execution
     * @throws NullPointerException if command is null
     * @throws IllegalArgumentException if delay less than or equal to zero
     */
    public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,
                                                     long initialDelay,
                                                     long delay,
                                                     TimeUnit unit);

scheduleAtFixedRate不同的是, scheduleWithFixedDelay方法的delay计时开始于上一次执行结束. 即下一次执行的时间为上一次执行完毕后再过delay时间.

实例:

    public static void testScheduleWithFixedDelay(){
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                try {
                    System.out.println("working at: " + getCurrentTime());
                    Thread.sleep(2000);

                } catch (InterruptedException e) {
                }
            }
        };

        ScheduledFuture<?> future = scheduledExecutorService.scheduleWithFixedDelay(runnable, 0, 2000, TimeUnit.MILLISECONDS);
        Thread main = Thread.currentThread();
        scheduledExecutorService.schedule(() -> main.interrupt(), 10, TimeUnit.SECONDS);
        try {
            future.get();
        } catch (InterruptedException | ExecutionException e) {
            future.cancel(true);
        }
    }

输出:

working at: 23:12:07
working at: 23:12:11
working at: 23:12:15

可以看出下一次执行都是在上一次执行完毕后的2000毫秒后 (注意一次执行花费2000毫秒).

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 136,029评论 19 139
  • 网络上关于java定时器的文章真的是错误百出,给我的学习造成了很大的困扰,Timer根本就没有线程安全问题,Tim...
    江江的大猪阅读 5,826评论 0 37
  • Timer 定时器相信都不会陌生,之所以拿它来做源码分析,是发现整个控制流程可以体现很多有意思的东西。 在业务开发...
    石先阅读 11,501评论 2 13
  • 2016.08.02到2016.08.06,我给自己放了一个假期。在这段时间里,我选择离开杭州,收拾以往的心情,从...
    Jerry_h阅读 3,875评论 0 0
  • 盘锦市兴隆台区生态园小区,位于市区东南角,向海大道东侧。园内道路纵横,湖水环绕,绿树成荫,花卉成片。五区,...
    五月蒹葭阅读 1,400评论 0 0

友情链接更多精彩内容