乐趣区

关于高并发:高并发ScheduledThreadPoolExecutor与Timer的区别和简单示例

JDK 1.5 开始提供 ScheduledThreadPoolExecutor 类,ScheduledThreadPoolExecutor 类继承 ThreadPoolExecutor 类重用线程池实现了工作的周期性调度性能。在 JDK 1.5 之前,实现工作的周期性调度次要应用的是 Timer 类和 TimerTask 类。本文,就简略介绍下 ScheduledThreadPoolExecutor 类与 Timer 类的区别,ScheduledThreadPoolExecutor 类相比于 Timer 类来说,到底有哪些劣势,以及二者别离实现任务调度的简略示例。

二者的区别

线程角度

  • Timer 是单线程模式,如果某个 TimerTask 工作的执行工夫比拟久,会影响到其余工作的调度执行。
  • ScheduledThreadPoolExecutor 是多线程模式,并且重用线程池,某个 ScheduledFutureTask 工作执行的工夫比拟久,不会影响到其余工作的调度执行。

零碎工夫敏感度

  • Timer 调度是基于操作系统的相对工夫的,对操作系统的工夫敏感,一旦操作系统的工夫扭转,则 Timer 的调度不再准确。
  • ScheduledThreadPoolExecutor 调度是基于绝对工夫的,不受操作系统工夫扭转的影响。

是否捕捉异样

  • Timer 不会捕捉 TimerTask 抛出的异样,加上 Timer 又是单线程的。一旦某个调度工作出现异常,则整个线程就会终止,其余须要调度的工作也不再执行。
  • ScheduledThreadPoolExecutor 基于线程池来实现调度性能,某个工作抛出异样后,其余工作仍能失常执行。

工作是否具备优先级

  • Timer 中执行的 TimerTask 工作整体上没有优先级的概念,只是依照零碎的相对工夫来执行工作。
  • ScheduledThreadPoolExecutor 中执行的 ScheduledFutureTask 类实现了 java.lang.Comparable 接口和 java.util.concurrent.Delayed 接口,这也就阐明了 ScheduledFutureTask 类中实现了两个十分重要的办法,一个是 java.lang.Comparable 接口的 compareTo 办法,一个是 java.util.concurrent.Delayed 接口的 getDelay 办法。在 ScheduledFutureTask 类中 compareTo 办法办法实现了工作的比拟,间隔下次执行的工夫距离短的工作会排在后面,也就是说,间隔下次执行的工夫距离短的工作的优先级比拟高。而 getDelay 办法则可能返回间隔下次工作执行的工夫距离。

是否反对对工作排序

  • Timer 不反对对工作的排序。
  • ScheduledThreadPoolExecutor 类中定义了一个动态外部类 DelayedWorkQueue,DelayedWorkQueue 类实质上是一个有序队列,为须要调度的每个工作依照间隔下次执行工夫距离的大小来排序

是否获取返回的后果

  • Timer 中执行的 TimerTask 类只是实现了 java.lang.Runnable 接口,无奈从 TimerTask 中获取返回的后果。
  • ScheduledThreadPoolExecutor 中执行的 ScheduledFutureTask 类继承了 FutureTask 类,可能通过 Future 来获取返回的后果。

通过以上对 ScheduledThreadPoolExecutor 类和 Timer 类的剖析比照,置信在 JDK 1.5 之后,就没有应用 Timer 来实现定时任务调度的必要了。

二者简略的示例

这里,给出应用 Timer 和 ScheduledThreadPoolExecutor 实现定时调度的简略示例,为了简便,我这里就间接应用匿名外部类的模式来提交工作。

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 类 

ScheduledThreadPoolExecutor 类简略示例

源代码示例如下所示。

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 和 ScheduledThreadPoolExecutor 还有其余的应用办法,这里,我就简略列出以上两个应用示例,更多的应用办法大家能够自行实现。

退出移动版