【Java】15.ScheduledExecutorService

来源:互联网 发布:氧传感器数据多少正常 编辑:程序博客网 时间:2024/06/13 23:03
1.官方资料

The java.util.concurrent.ScheduledExecutorService is an ExecutorService which can schedule tasks to run after a delay, or to execute repeatedly with a fixed interval of time in between each execution. Tasks are executed asynchronously by a worker thread, and not by the thread handing the task to the ScheduledExecutorService. ScheduledExecutorService Example

Here is a simple ScheduledExecutorService example:

ScheduledExecutorService scheduledExecutorService =        Executors.newScheduledThreadPool(5);ScheduledFuture scheduledFuture =    scheduledExecutorService.schedule(new Callable() {        public Object call() throws Exception {            System.out.println("Executed!");            return "Called!";        }    },    5,    TimeUnit.SECONDS);

First a ScheduledExecutorService is created with 5 threads in. Then an anonymous implementation of the Callable interface is created and passed to the schedule() method. The two last parameters specify that the Callable should be executed after 5 seconds. ScheduledExecutorService Implementations

Since ScheduledExecutorService is an interface, you will have to use its implementation in the java.util.concurrent package, in order to use it. ScheduledExecutorService as the following implementation:

ScheduledThreadPoolExecutor

Creating a ScheduledExecutorService

How you create an ScheduledExecutorService depends on the implementation you use. However, you can use the Executors factory class to create ScheduledExecutorService instances too. Here is an example:

ScheduledExecutorService scheduledExecutorService =        Executors.newScheduledThreadPool(5);

ScheduledExecutorService Usage

Once you have created a ScheduledExecutorService you use it by calling one of its methods:

schedule (Callable task, long delay, TimeUnit timeunit)schedule (Runnable task, long delay, TimeUnit timeunit)scheduleAtFixedRate (Runnable, long initialDelay, long period, TimeUnit timeunit)scheduleWithFixedDelay (Runnable, long initialDelay, long period, TimeUnit timeunit)

I will briefly cover each of these methods below. schedule (Callable task, long delay, TimeUnit timeunit)

This method schedules the given Callable for execution after the given delay.

The method returns a ScheduledFuture which you can use to either cancel the task before it has started executing, or obtain the result once it is executed.

Here is an example:

ScheduledExecutorService scheduledExecutorService =        Executors.newScheduledThreadPool(5);ScheduledFuture scheduledFuture =    scheduledExecutorService.schedule(new Callable() {        public Object call() throws Exception {            System.out.println("Executed!");            return "Called!";        }    },    5,    TimeUnit.SECONDS);System.out.println("result = " + scheduledFuture.get());scheduledExecutorService.shutdown();

This example outputs:

Executed!result = Called!

schedule (Runnable task, long delay, TimeUnit timeunit)

This method works like the method version taking a Callable as parameter, except a Runnable cannot return a value, so the ScheduledFuture.get() method returns null when the task is finished. scheduleAtFixedRate (Runnable, long initialDelay, long period, TimeUnit timeunit)

This method schedules a task to be executed periodically. The task is executed the first time after the initialDelay, and then recurringly every time the period expires.

If any execution of the given task throws an exception, the task is no longer executed. If no exceptions are thrown, the task will continue to be executed until the ScheduledExecutorService is shut down.

If a task takes longer to execute than the period between its scheduled executions, the next execution will start after the current execution finishes. The scheduled task will not be executed by more than one thread at a time. scheduleWithFixedDelay (Runnable, long initialDelay, long period, TimeUnit timeunit)

This method works very much like scheduleAtFixedRate() except that the period is interpreted differently.

In the scheduleAtFixedRate() method the period is interpreted as a delay between the start of the previous execution, until the start of the next execution.

In this method, however, the period is interpreted as the delay between the end of the previous execution, until the start of the next. The delay is thus between finished executions, not between the beginning of executions. ScheduledExecutorService Shutdown

Just like an ExecutorService, the ScheduledExecutorService needs to be shut down when you are finished using it. If not, it will keep the JVM running, even when all other threads have been shut down.

You shut down a ScheduledExecutorService using the shutdown() or shutdownNow() methods which are inherited from the ExecutorService interface. See the ExecutorService Shutdown section for more information.

2.分析

ScheduledExecutorService,是基于线程池设计的定时任务类,每个调度任务都会分配到线程池中的一个线程去执行,也就是说,任务是并发执行,互不影响。

需要注意,只有当调度任务来的时候,ScheduledExecutorService才会真正启动一个线程,其余时间ScheduledExecutorService都是出于轮询任务的状态。

如果只是想简单的写个定时任务,比如10分钟跑一次,那么ScheduledExecutorService是比较方便的,下面举个简单的例子(摘自https://www.cnblogs.com/junrong624/p/5504711.html)

public class CrawlerRun {   private static final Logger logger = LoggerFactory.getLogger(CrawlerRun.class);   public static void main(String[] args) {      ScheduledExecutorService service = Executors.newScheduledThreadPool(8);//先定义8个线程空间      final ScheduledFuture<?> future = service.scheduleAtFixedRate(new CrawlerTest(), 0,10,                 TimeUnit.MINUTES);//CrawlerTest()是一个实现Runnable接口的类,会自动运行里面的run()方法,0的意思就是启动等待时间,这里就是直接运行,                                 1010分钟,要是想小时,就把TimeUnit.MINUTES换成 TimeUnit.HOURS      //使用1个线程         Thread t= new Thread(new Runnable() {                public void run() {                    try {                        future.get();                    } catch (Exception e) {                        logger.error(e.getCause().getMessage(), e.getCause());//日志信息输出                        future.cancel(false);//关闭线程                    }                }        });        t.start() ;   }}

通过ScheduledExecutorService执行的周期任务,如果任务执行过程中抛出了异常,那么过ScheduledExecutorService就会停止执行任务,且也不会再周期地执行该任务了。所以你如果想保住任务都一直被周期执行,那么catch一切可能的异常。