zoukankan      html  css  js  c++  java
  • 带你学会区分Scheduled Thread Pool Executor 与Timer

    摘要:本文简单介绍下Scheduled Thread Pool Executor类与Timer类的区别,Scheduled Thread Pool Executor类相比于Timer类来说,究竟有哪些优势,以及二者分别实现任务调度的简单示例。

    本文分享自华为云社区《【高并发】ScheduledThreadPoolExecutor与Timer的区别和简单示例》,作者:冰 河 。

    JDK 1.5开始提供Scheduled Thread Pool Executor类,Scheduled Thread Pool Executor类继承Thread Pool Executor类重用线程池实现了任务的周期性调度功能。在JDK 1.5之前,实现任务的周期性调度主要使用的是Timer类和Timer Task类。本文,就简单介绍下Scheduled Thread Pool Executor类与Timer类的区别,Scheduled Thread Pool Executor类相比于Timer类来说,究竟有哪些优势,以及二者分别实现任务调度的简单示例。

    二者的区别

    线程角度

    • Timer是单线程模式,如果某个TimerTask任务的执行时间比较久,会影响到其他任务的调度执行。
    • Scheduled Thread Pool Executor是多线程模式,并且重用线程池,某个Scheduled Future Task任务执行的时间比较久,不会影响到其他任务的调度执行。

    系统时间敏感度

    • Timer调度是基于操作系统的绝对时间的,对操作系统的时间敏感,一旦操作系统的时间改变,则Timer的调度不再精确。
    • Scheduled Thread Pool Executor调度是基于相对时间的,不受操作系统时间改变的影响。

    是否捕获异常

    • Timer不会捕获Timer Task抛出的异常,加上Timer又是单线程的。一旦某个调度任务出现异常,则整个线程就会终止,其他需要调度的任务也不再执行。
    • Scheduled Thread Pool Executor基于线程池来实现调度功能,某个任务抛出异常后,其他任务仍能正常执行。

    任务是否具备优先级

    • Timer中执行的Timer Task任务整体上没有优先级的概念,只是按照系统的绝对时间来执行任务。
    • Scheduled Thread Pool Executor中执行的Scheduled Future Task类实现了java.lang.Comparable 接口和java.util.concurrent.Delayed 接口,这也就说明了Scheduled Future Task类中实现了两个非常重要的方法,一个是java.lang.Comparable 接口的compare To方法,一个是java.util.concurrent.Delayed接口的get Delay方法。在Scheduled Future Task类中compare To方法实现了任务的比较,距离下次执行的时间间隔短的任务会排在前面,也就是说,距离下次执行的时间间隔短的任务的优先级比较高。而get Delay 方法则能够返回距离下次任务执行的时间间隔。

    是否支持对任务排序

    • Timer不支持对任务的排序。
    • Scheduled Thread Pool Executor类中定义了一个静态内部类Delayed Work Queue ,Delayed Work Queue 类本质上是一个有序队列,为需要调度的每个任务按照距离下次执行时间间隔的大小来排序

    能否获取返回的结果

    • Timer中执行的Timer Task类只是实现了java.lang.Runnable 接口,无法从Timer Task 中获取返回的结果。
    • Scheduled Thread Pool Executor中执行的Scheduled Future Task类继承了Future Task 类,能够通过Future来获取返回的结果。

    通过以上对Scheduled Thread Pool Executor 类和Timer类的分析对比,相信在JDK 1.5之后,就没有使用Timer来实现定时任务调度的必要了。

    二者简单的示例

    这里,给出使用Timer和Scheduled Thread Pool Executor 实现定时调度的简单示例,为了简便,我这里就直接使用匿名内部类的形式来提交任务。

    Timer类简单示例

    源代码示例如下所示。

    package io.binghe.concurrent.lab09;
    
    import java.util.Timer;
    import java.util.TimerTask;
    
    /**
     * @author binghe
     * @version 1.0.0
     * @description 测试Timer
     */
    public class TimerTest {
    
        public static void main(String[] args) throws InterruptedException {
            Timer timer = new Timer();
            timer.scheduleAtFixedRate(new TimerTask() {
                @Override
                public void run() {
                    System.out.println("测试Timer类");
                }
            }, 1000, 1000);
            Thread.sleep(10000);
            timer.cancel();
        }
    }

    运行结果如下所示。

    测试Timer类
    测试Timer类
    测试Timer类
    测试Timer类
    测试Timer类
    测试Timer类
    测试Timer类
    测试Timer类
    测试Timer类
    测试Timer类

    Scheduled Thread Pool Executor类简单示例

    源代码示例如下所示。

    package io.binghe.concurrent.lab09;
    
    import java.util.concurrent.*;
    
    /**
     * @author binghe
     * @version 1.0.0
     * @description 测试ScheduledThreadPoolExecutor
     */
    public class ScheduledThreadPoolExecutorTest {
        public static void main(String[] args) throws  InterruptedException {
            ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(3);
            scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
                @Override
                public void run() {
                    System.out.println("测试测试ScheduledThreadPoolExecutor");
                }
            }, 1, 1, TimeUnit.SECONDS);
    
            //主线程休眠10秒
            Thread.sleep(10000);
    
            System.out.println("正在关闭线程池...");
            // 关闭线程池
            scheduledExecutorService.shutdown();
            boolean isClosed;
            // 等待线程池终止
            do {
                isClosed = scheduledExecutorService.awaitTermination(1, TimeUnit.DAYS);
                System.out.println("正在等待线程池中的任务执行完成");
            } while(!isClosed);
    
            System.out.println("所有线程执行结束,线程池关闭");
        }
    }

    运行结果如下所示。

    测试测试ScheduledThreadPoolExecutor
    测试测试ScheduledThreadPoolExecutor
    测试测试ScheduledThreadPoolExecutor
    测试测试ScheduledThreadPoolExecutor
    测试测试ScheduledThreadPoolExecutor
    测试测试ScheduledThreadPoolExecutor
    测试测试ScheduledThreadPoolExecutor
    测试测试ScheduledThreadPoolExecutor
    测试测试ScheduledThreadPoolExecutor
    正在关闭线程池...
    测试测试ScheduledThreadPoolExecutor
    正在等待线程池中的任务执行完成
    所有线程执行结束,线程池关闭

    注意:关于Timer和Scheduled Thread Pool Executor 还有其他的使用方法,这里,我就简单列出以上两个使用示例,更多的使用方法大家可以自行实现。

     

    点击关注,第一时间了解华为云新鲜技术~

  • 相关阅读:
    ASP.NET,flexpaper,SWFTools 实现简单的PDF显示(一)
    ASP.NET,flexpaper,SWFTools 实现简单的PDF显示(三)
    一个获取远程客户端真实IP的例子
    用微软Chart制作图表
    快速读取xml节点内容
    ASP.NET 网站路径【摘自MSDN】
    SqlServer连接字符串相关记录
    视图研究一二
    天大计算机研究生的求职总结
    一个计算机系研究生毕业以后的人生规划(转)
  • 原文地址:https://www.cnblogs.com/huaweiyun/p/15318876.html
Copyright © 2011-2022 走看看