ScheduledThreadPoolExecutor浅析

  • ScheduledThreadPoolExecutor继承自ThreadPoolExecutor。它主要用来在给定的延迟之后执行任务,或者定期执行任务。
  • ScheduledThreadPoolExecutor的功能与Timer类似,但比Timer更强大,更灵活,Timer对应的是单个后台线程,而ScheduledThreadPoolExecutor可以在构造函数中指定多个对应的后台线程数。

1 创建ScheduledThreadPoolExecutor

  • ScheduledThreadPoolExecutor通常使用工厂类Executors来创建,Executors可以创建两种类型的ScheduledThreadPoolExecutor,如下:
  • (1)ScheduledThreadPoolExecutor:可以执行并行任务也就是多条线程同时执行。
  • (2)SingleThreadScheduledExecutor:可以执行单条线程。

1.1 ScheduledThreadPoolExecutor

创建ScheduledThreadPoolExecutor的方法构造如下:

public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize, ThreadFactory threadFactory)

1.2 SingleThreadScheduledExecutor

创建SingleThreadScheduledExecutor的方法构造如下:

public static ScheduledExecutorService newSingleThreadScheduledExecutor()
public static ScheduledExecutorService newSingleThreadScheduledExecutor(ThreadFactory threadFactory)

1.3 创建实例对象

创建实例对象代码如下

ScheduledExecutorService scheduledThreadPoolExecutor=Executors.newScheduledThreadPool(5);

ScheduledExecutorService singleThreadScheduledExecutor=Executors.newSingleThreadScheduledExecutor();

2 ScheduledThreadPoolExecutor执行机制分析

6b67d1561cfaa41a82514ca8b29056ed.png

分析:DelayQueue是一个无界队列,所以ThreadPoolExecutor的maximumPoolSize在ScheduledThreadPoolExecutor中无意义。
ScheduledThreadPoolExecutor的执行主要分为以下两个部分

  • (1)当调用ScheduledThreadPoolExecutor的scheduleAtFixedRate()方法或者scheduleWithFixedDelay()方法时,会向ScheduledThreadPoolExecutor的DelayQueue添加一个实现了RunnableScheduledFuture接口的ScheduleFutureTask。
  • (2)线程池中的线程从DelayQueue中获取ScheduleFutureTask,然后执行任务。

3 使用场景

3.1 ScheduledThreadPoolExecutor和SingleThreadScheduledExecutor的适用场景

  • ScheduledThreadPoolExecutor:适用于多个后台线程执行周期性任务,同时为了满足资源管理的需求而需要限制后台线程数量的应用场景。
  • SingleThreadScheduledExecutor:适用于需要单个后台线程执行周期任务,同时需要保证任务顺序执行的应用场景。

4 ScheduledThreadPoolExecutor使用案例

我们创建一个Runnable的对象,然后使用ScheduledThreadPoolExecutor的Scheduled()来执行延迟任务,输出执行时间即可:

4.1 该类延迟执行的方法:

public ScheduledFuture schedule(Runnable command,long delay, TimeUnit unit);

参数解析:

  • command:就是一个实现Runnable接口的类
  • delay:延迟多久后执行。
  • unit:用于指定keepAliveTime参数的时间单位,这是一个枚举,常用的有TimeUnit.MILLISECONDS(毫秒),TimeUnit.SECONDS(秒)以及TimeUnit.MINUTES(分钟)等。
    schedule
//创建一个工作线程继承Runnable
public class WorkerThread implements Runnable{
  @Override
  public void run() {
     System.out.println(Thread.currentThread().getName()+" Start. Time = "+getNowDate());
       threadSleep();
       System.out.println(Thread.currentThread().getName()+" End. Time = "+getNowDate());
    
  }
  /**
   * 睡3秒
   */
  public void threadSleep(){
    try {
      Thread.sleep(3000);
    } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }
   /**
    * 获取现在时间
    * 
    * @return 返回时间类型 yyyy-MM-dd HH:mm:ss
    */
  public static String getNowDate() {
      Date currentTime = new Date();
      SimpleDateFormat formatter; 
        formatter = new SimpleDateFormat ("yyyy-MM-dd HH:mm:ss"); 
        String ctime = formatter.format(currentTime); 
      return ctime;
     }
}
public class ScheduledThreadPoolTest {
  
  public static void main(String[] args) {
    ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
     try {
      //schedule to run after sometime
      System.out.println("Current Time = "+getNowDate());
      for(int i=0; i<3; i++){
          Thread.sleep(1000);
          WorkerThread worker = new WorkerThread();
          //延迟5秒后执行
          scheduledThreadPool.schedule(worker, 10, TimeUnit.SECONDS);
      }
      Thread.sleep(3000);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
      scheduledThreadPool.shutdown();
      while(!scheduledThreadPool.isTerminated()){
          //wait for all tasks to finish
      }
      System.out.println("Finished all threads");
  }
  
   /**
    * 获取现在时间
    * 
    * @return 返回时间类型 yyyy-MM-dd HH:mm:ss
    */
   public static String getNowDate() {
    Date currentTime = new Date();
    SimpleDateFormat formatter; 
      formatter = new SimpleDateFormat ("yyyy-MM-dd HH:mm:ss"); 
      String ctime = formatter.format(currentTime); 
    return ctime;
   }
}
9cc165d7ac247dbceff5524eb7faf2d8.png

线程任务确实在10秒延迟后才开始执行。这就是schedule()方法的使用。
** scheduleAtFixedRate**

public ScheduledFuture scheduleAtFixedRate(Runnable command,long initialDelay,long period,TimeUnit unit)

scheduleAtFixedRate方法的作用是预定在初始的延迟结束后,周期性地执行给定的任务,周期长度为period,其中initialDelay为初始延迟。

scheduleWithFixedDelay

public ScheduledFuture scheduleWithFixedDelay(Runnable command,long initialDelay,long delay,TimeUnit unit);

scheduleWithFixedDelay方法的作用是预定在初始的延迟结束后周期性地执行给定任务,在一次调用完成和下一次调用开始之间有长度为delay的延迟,其中initialDelay为初始延迟。
案例代码

//周期函数测试类
public class ScheduledTask {
  public ScheduledThreadPoolExecutor se = new ScheduledThreadPoolExecutor(5);
  public static void main(String[] args) {
    new ScheduledTask();
  }
  public void fixedPeriodSchedule() {
    // 设定可以循环执行的runnable,初始延迟为0,这里设置的任务的间隔为1秒
    for(int i=0;i<5;i++){
      se.scheduleAtFixedRate(new FixedSchedule(), 0, 1, TimeUnit.SECONDS);
    }
  }
  public ScheduledTask() {
    fixedPeriodSchedule();
  }
  class FixedSchedule implements Runnable {
    public void run() {
      System.out.println("当前线程:"+Thread.currentThread().getName()+"  当前时间:"+new Date(System.currentTimeMillis()));
    }
  }
}

SingleThreadScheduledExecutor的使用的方法基本是类似

cankao

https://juejin.im/entry/57ad83932e958a005442862c

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容