关于java:面试突击34如何使用线程池执行定时任务

5次阅读

共计 3599 个字符,预计需要花费 9 分钟才能阅读完成。

在 Java 语言中,有两个线程池能够执行定时工作:ScheduledThreadPool 和 SingleThreadScheduledExecutor,其中 SingleThreadScheduledExecutor 能够看做是 ScheduledThreadPool 的单线程版本,它的用法和 ScheduledThreadPool 是一样的,所以本文重点来看 ScheduledThreadPool 线程池的应用。
ScheduledThreadPool 执行定时工作的办法有以下 3 个:

  1. 应用 schedule 办法执行定时工作,只执行一次定时工作。
  2. 应用 scheduleAtFixedRate 办法执行定时工作,执行屡次定时工作。
  3. 应用 scheduleWithFixedDelay 办法执行定时工作,执行屡次定时工作。

接下来咱们看这 3 个办法的具体应用和区别。

1.schedule

schedule 办法只能执行一次定时工作,它须要传递 3 个参数:

  • 第 1 个参数:传递一个工作,Runnable 或 Callable 对象;
  • 第 2 个参数:增加定时工作后,再过多久开始执行定时工作;
  • 第 3 个参数:工夫单位,配合参数 2 一起应用。

上面咱们创立一个 3 秒当前执行的定时工作:

import java.time.LocalDateTime;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class ScheduledThreadPoolExample {public static void main(String[] args) throws InterruptedException {
        // 创立 ScheduledThreadPool 线程池
        ScheduledExecutorService threadPool = Executors.newScheduledThreadPool(10);
        System.out.println("schedule 办法增加工作:" + LocalDateTime.now());
        threadPool.schedule(new Runnable() {
            @Override
            public void run() {System.out.println("执行 schedule 办法:" + LocalDateTime.now());
            }
        }, 3, TimeUnit.SECONDS); // 3s 之后执行

        // 以下代码是给业务办法一个工夫对照信息
        TimeUnit.SECONDS.sleep(10); // 休眠 10s
        System.out.println("以后工夫:" + LocalDateTime.now());
    }
}

以上程序的执行后果如下图所示:

从上述后果中能够看出,应用 schedule 办法只能执行一次定时工作。

2.scheduleAtFixedRate

scheduleAtFixedRate 办法能够执行屡次定时工作,此办法须要 4 个参数:

  • 第 1 个参数:传递一个工作,Runnable 或 Callable 对象;
  • 第 2 个参数:增加定时工作后,再过多久开始执行定时工作;
  • 第 3 个参数:定时工作执行的工夫距离;
  • 第 4 个参数:工夫单位,配合参数 2 和参数 3 一起应用。

上面咱们创立一个 3 秒后执行的定时工作,每个定时工作执行的工夫距离为 2 秒,实现代码如下:

import java.time.LocalDateTime;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class ScheduledThreadPoolExample {public static void main(String[] args) throws InterruptedException {
        // 创立 ScheduledThreadPool 线程池
        ScheduledExecutorService threadPool = Executors.newScheduledThreadPool(10);
        System.out.println("scheduleAtFixedRate 办法增加工作:" + LocalDateTime.now());
        threadPool.scheduleAtFixedRate(new Runnable() {
                                           @Override
                                           public void run() {System.out.println("执行 scheduleAtFixedRate 办法:" + LocalDateTime.now());
                                               // 休眠 2s
                                               try {TimeUnit.SECONDS.sleep(2);
                                               } catch (InterruptedException e) {e.printStackTrace();
                                               }
                                           }
                                       },
                3L, // 3s 后开始执行定时工作
                2L, // 定时工作的执行距离为 2s
                TimeUnit.SECONDS); // 形容下面两个参数的工夫单位
    }
}

以上程序的执行后果如下图所示:

从上述后果能够看出,当工作增加胜利之后,3s 后开始执行第一个定时工作,之后每隔 2s 执行一次定时工作。

3.scheduleWithFixedDelay

scheduleWithFixedDelay 办法的应用和 scheduleAtFixedRate 相似,但执行成果齐全不同,这个很容易了解如果成果一样就不必创立两个办法了。
scheduleWithFixedDelay 办法是在办法执行实现之后,再隔 N 秒执行下一个定时工作,和 scheduleAtFixedRate 的固定工夫执行不同,scheduleWithFixedDelay 办法的执行受定时工作执行的时长影响 ,比方以下代码:

import java.time.LocalDateTime;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class ScheduledThreadPoolExample {public static void main(String[] args) throws InterruptedException {
        // 创立 ScheduledThreadPool 线程池
        ScheduledExecutorService threadPool = Executors.newScheduledThreadPool(10);
        System.out.println("scheduleWithFixedDelay 办法增加工作:" + LocalDateTime.now());
        threadPool.scheduleWithFixedDelay(new Runnable() {
                                              @Override
                                              public void run() {System.out.println("执行 scheduleWithFixedDelay 办法:" + LocalDateTime.now());
                                                  // 休眠 2s
                                                  try {TimeUnit.SECONDS.sleep(2);
                                                  } catch (InterruptedException e) {e.printStackTrace();
                                                  }
                                              }
                                          },
                3L, // 3s 后开始执行定时工作
                2L, // 定时工作执行完 2s 之后,再执行下一个定时工作
                TimeUnit.SECONDS); // 形容下面两个参数的工夫单位
    }
}

以上程序的执行后果如下图所示:

从上述后果能够看出,定时工作在 3s 之后开始执行,当前每隔 4s 执行一次,这 4s 蕴含了,定时工作执行破费的 2s,加上每隔 2s 执行一次的工夫距离,也就是说 scheduleWithFixedDelay 是在工作执行完 N 秒之后,再执行下一次定时工作

总结

线程池执行定时工作的实现办法有 3 个:

  1. 应用 schedule 办法执行定时工作,只执行一次定时工作。
  2. 应用 scheduleAtFixedRate 办法执行定时工作,执行屡次定时工作,它的执行工夫距离是固定的,不受定时工作执行时长影响(定时工作工夫距离 > 工作执行工夫)。
  3. 应用 scheduleWithFixedDelay 办法执行定时工作,执行屡次定时工作,它是在定时工作执行完之后,再隔 N 秒开始执行下一次定时工作,它的执行工夫受定时工作执行时长影响。

是非审之于己,毁誉听之于人,得失安之于数。

公众号:Java 面试真题解析

面试合集:https://gitee.com/mydb/interview

正文完
 0