携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第5天,点击查看活动详情
ScheduleThreadPoolExecutor
使用
基于多线程、JVM
时间实现延时、定期任务执行类。于JDK1.5
版本开始提供ScheduleThreadPoolExecutor
类,继承自ThreadPoolExecutor
类重用线程池实现了任务的周期性调度功能。功能和Timer
类似,但是提供的功能更强大、更灵活。
类型
ScheduledThreadPoolExecutor
:执行并行任务也就是多条线程同时执行。SingleThreadScheduledExecutor
:执行单条线程。
使用
//一定延时后执行一次性任务
public ScheduledFuture<?> schedule(Runnable command,
long delay, TimeUnit unit);
public <V> ScheduledFuture<V> schedule(Callable<V> callable,
long delay, TimeUnit unit);
//一定延时后周期性执行某个任务
//间隔是固定的,无论上一个任务是否执行完成
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
long initialDelay,
long period,
TimeUnit unit);
//间隔是不固定的,其会在周期任务的上一个任务执行完成后才开始计时,并在指定时间间隔才可以执行任务
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,
long initialDelay,
long delay,
TimeUnit unit);
public static void main(String[] args) {
//指定核心线程数, Executors.newSingleThreadScheduledExecutor(),相当于corePoolSize = 1
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(10);
MyTask task1 = new MyTask("一次测试");
MyTask task2 = new MyTask("周期测试");
MyTask task3 = new MyTask("延迟测试");
long delay = 0L;
long period = 1000L;
scheduledThreadPool.schedule(task1, delay, TimeUnit.MILLISECONDS);
scheduledThreadPool.scheduleAtFixedRate(task2, delay, period, TimeUnit.MILLISECONDS);
scheduledThreadPool.scheduleWithFixedDelay(task3, delay, period, TimeUnit.MILLISECONDS);
}
static class MyTask implements Runnable {
private String taskName;
public MyTask(String taskName) {
this.taskName = taskName;
}
@Override
public void run() {
try {
Thread.sleep(2000L);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println(taskName + "执行时间:" + new Date() + "------------"
+ "线程:" + Thread.currentThread().getName());
}
}
从结果可以看出执行的时候使用了是不同的线程来执行。
schedule()
:延时一定时间后执行一次,后续不在继续执行scheduleAtFixedRate()
:这个方法的作用是周期性的调度task
执行。第一次执行的延迟根据initialDelay
参数确定,以后每一次执行都间隔period
时长。如果task
的执行时间大于定义的period
,那么下一个线程将在当前线程完成之后再执行。整个调度保证不会出现一个以上任务同时执行。 所以我们可以发现上面“周期测试”并不是按照1秒间隔来执行,而是2秒。scheduleWithFixedDelay()
:这个方法的作用也是周期性的调度,period
指的当前任务的结束执行时间到下个任务的开始执行时间。 所以我们发现上面“延迟测试” 并不是按照1秒执行,而是3秒。
假如我们使用完ScheduledExecutorService
需要关闭,如果不关闭, JVM
会一直运行,即使所有线程都关闭了。关闭可以使用shutdown()
和shutdownNow()
两个方法。