JAVA线程池:ScheduledThreadPoolExecutor

Posted Vashon_杨博程

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JAVA线程池:ScheduledThreadPoolExecutor相关的知识,希望对你有一定的参考价值。

前言

自JDK1.5开始,JDK提供了ScheduledThreadPoolExecutor类来支持周期性任务的调度。在这之前的实现需要依靠Timer和TimerTask或者其它第三方工具来完成,但Timer有不少的缺陷:

  • Timer是单线程模式;
  • 如果在执行任务期间某个TimerTask耗时较久,那么就会影响其它任务的调度;
  • Timer的任务调度是基于绝对时间的,对系统时间敏感;
  • Timer不会捕获执行TimerTask时所抛出的异常,由于Timer是单线程,所以一旦出现异常,则线程就会终止,其他任务也得不到执行。

ScheduledThreadPoolExecutor继承ThreadPoolExecutor来重用线程池的功能,它的实现方式如下:

  • 将任务封装成ScheduledFutureTask对象,ScheduledFutureTask基于相对时间,不受系统时间的改变所影响;
  • ScheduledFutureTask实现了java.lang.Comparable接口和java.util.concurrent.Delayed接口,所以有两个重要的方法:compareTo和getDelay。compareTo方法用于比较任务之间的优先级关系,如果距离下次执行的时间间隔较短,则优先级高;getDelay方法用于返回距离下次任务执行时间的时间间隔;
  • ScheduledThreadPoolExecutor定义了一个DelayedWorkQueue,它是一个有序队列,会通过每个任务按照距离下次执行时间间隔的大小来排序;
  • ScheduledFutureTask继承自FutureTask,可以通过返回Future对象来获取执行的结果。

通过如上的介绍,可以对比一下Timer和ScheduledThreadPoolExecutor:

TimerScheduledThreadPoolExecutor
单线程多线程
单个任务执行时间影响其他任务调度多线程,不会影响
基于绝对时间基于相对时间
一旦执行任务出现异常不会捕获,其他任务得不到执行多线程,单个任务的执行不会影响其他线程

Timer和TimerTask的使用

这个大家应该都是会使用的了,示例代码如下:

Timer  timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                log.e("time:");

            }
        }, 2000, 40);//2000表示第一次执行任务延迟时间,40表示以后每隔多长时间执行一次run里面的任务

ScheduledThreadPoolExecutor的使用

 SchedualedThreadPoolExecutor 接收SchduledFutureTask类型的任务,是线程池调度任务的最小单位,有三种提交任务的方式:

  •  schedule:延迟多长时间之后只执行一次;
  •  scheduledAtFixedRate:延迟指定时间后执行一次,之后按照固定的时长周期执行;
  •  scheduledWithFixedDelay:延迟指定时间后执行一次,之后按照:上一次任务执行时长 + 周期的时长 的时间去周期执行;

/**
 * 定时任务线程池
 */
public class ScheduledThreadPoolExecutorTest {
    public static void main(String args[]) {
     
        ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
        int time = 2000; // 延迟2秒执行
        MyTask task = new MyTask("定时任务线程");

        // 1、schedule:延迟多长时间之后只执行一次(延迟2秒执行)
        scheduledThreadPool.schedule(task, time, TimeUnit.MILLISECONDS);

        // 2、scheduledAtFixedRate:延迟指定时间后执行一次,之后按照固定的时长周期执行(延迟2秒执行,之后间隔3秒执行)
        //scheduledThreadPool.scheduleAtFixedRate(task,time,3000,TimeUnit.MILLISECONDS);

        // 3、scheduledWithFixedDelay:延迟指定时间后执行一次,之后按照:上一次任务执行时长 + 周期的时长 的时间去周期执行(延迟2秒执行,之后间隔上次任务执行时长+周期时长执行)
        scheduledThreadPool.scheduleWithFixedDelay(task,time,3000,TimeUnit.MILLISECONDS);

        //mScheduledThreadPoolExecutor.shutdown();
    }
}

class MyTask implements Runnable {

    private String TAG = "";

    public MyTask(String tag) {
        TAG = tag;
    }

    @Override
    public void run() {
        System.out.println(TAG + "\\t" + System.currentTimeMillis());
    }
}

以上是关于JAVA线程池:ScheduledThreadPoolExecutor的主要内容,如果未能解决你的问题,请参考以下文章

Java线程池

java创建线程池都有哪些

java线程池

java线程池原理

JAVA线程池使用哪一种比较好

如何使用java语言实现一个线程池,不使用jdk自带的线程池