3

带你学会区分Scheduled Thread Pool Executor 与Timer

 2 years ago
source link: https://my.oschina.net/u/4526289/blog/5266738
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

带你学会区分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 还有其他的使用方法,这里,我就简单列出以上两个使用示例,更多的使用方法大家可以自行实现。

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


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK