ScheduledExecutorService
ScheduledExecutorService是ExecutorService的子接口,具备了延迟运行或定期执行任务的能力。
1、常用获取方式
(注:还是通过 Executors. 的方式进行调用)
1)static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)
—— 创建一个可重用固定线程数的线程池且允许延迟运行或(重复/)定期执行任务
static ScheduledExecutorService newScheduledThreadPool(int corePoolSize, ThreadFactory threadFactory)
—— 创建一个可重用固定线程数的线程池,且线程池中的所有线程都使用ThreadFactory来创建,且允许延迟运行或定期执行任务
2)static ScheduledExecutorService newSingleThreadScheduledExecutor()
—— 创建一个单线程执行程序,它允许在给定延迟后运行命令或者(重复/)定期地执行任务
static ScheduledExecutorService newSingleThreadScheduledExecutor(ThreadFactory threadFactory)
—— 创建一个单线程执行程序,且线程池中的所有线程都使用ThreadFactory来创建,且允许在给定延迟后运行命令或者定期地执行任务
2、常用方法
<V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit)
—— 延迟时间单位是unit,数量是delay的时间后执行callable
ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit)
—— 延迟时间单位是unit,数量是delay的时间后执行command
下面的方法可以重复执行任务:(两种间隔方式)
ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit)
—— 延迟时间单位是unit,数量是initialDelay的时间后,每间隔period时间重复执行一次command
ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit)
—— 创建并执行一个在给定初始延迟后首次启用的定期操作,随后,在每一次执行终止和下一次执行开始之间都存在给定的延迟(即:同上面一样,也是重复执行,但是,延迟时间是从第一次(仅仅是第一次?还是每次?:每一次)重复/执行完后的时间开始算起的)
示意图:
上面是scheduleAtFixedRate(...),下面是scheduleWithFixedDelay(...)
3、代码示例
(1)最简单的延迟执行(一个或多个任务)
ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit)
package com.zhoulz.demo03;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
* 测试ScheduledExecutorService接口中延迟执行任务和重复执行任务的功能
*/
public class ScheduledExecutorServiceDemo01 {
public static void main(String[] args) {
// 1、获取一个具备延迟执行任务的线程池对象
ScheduledExecutorService es = Executors.newScheduledThreadPool(3);
// 2、创建多个任务对象,提交任务,每个任务延迟2秒执行
// (同样,这个任务可以单独创建一个类,也可以通过匿名内部类的方式)
// 提交任务用方法,而不是submit()方法了
// 下面先提交一个任务
//es.schedule(new MyRunnable(666),2, TimeUnit.SECONDS);
// 提交多个任务—— 通过for循环
for (int i = 1; i <= 10; i++) {
es.schedule(new MyRunnable(i),2, TimeUnit.SECONDS);
}
// 下面这个打印是在main方法中的,不会延迟。
// 所以,正常情况是:打印“over”后,延迟2秒后执行任务
System.out.println("over");
}
}
class MyRunnable implements Runnable{
private int id;
public MyRunnable(int id) {
this.id = id;
}
@Override
public void run() {
String name = Thread.currentThread().getName();
System.out.println(name + "执行了任务:" + id);
}
}
结果:
(2)只执行一个任务,但是使其重复执行
ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit)
package com.zhoulz.demo03;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
/**
* 测试ScheduledExecutorService接口中延迟执行任务和重复执行任务的功能
*/
public class ScheduledExecutorServiceDemo02 {
public static void main(String[] args) {
// 1、获取一个具备延迟执行任务的线程池对象
ScheduledExecutorService es = Executors.newScheduledThreadPool(3, new ThreadFactory() {
int n = 1;
@Override
public Thread newThread(Runnable r) {
return new Thread(r,"自定义的线程名zlz:"+ n++);
}
});
// 2、创建多个任务对象,提交任务,每个任务延迟2秒执行
// (匿名内部类的方式,见上面)
// 下面不再提交多个任务,而是就提交1个任务,并让其重复执行
// 初识延迟1秒,间隔2秒
es.scheduleAtFixedRate(new MyRunnable2(666),1,2,TimeUnit.SECONDS);
// 提交多个任务—— 通过for循环
/*for (int i = 1; i <= 10; i++) {
es.schedule(new MyRunnable2(i),2, TimeUnit.SECONDS);
}*/
System.out.println("over");
}
}
class MyRunnable2 implements Runnable{
private int id;
public MyRunnable2(int id) {
this.id = id;
}
@Override
public void run() {
String name = Thread.currentThread().getName();
// 模拟任务执行时间1.5秒,这个1.5秒是在间隔时间2秒钟之类的
try {
Thread.sleep(1500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(name + "执行了任务:" + id);
}
}
结果:
(3)只执行一个任务,但是使其重复执行
区别于(2),所用的是scheduleWithFixedDelay()方法 —— 来提交任务
ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit)
同时,获取线程的方式用的是:
(即单线程的,见下面,(2)用的是指定线程newScheduledThreadPool() )
static ScheduledExecutorService newSingleThreadScheduledExecutor(ThreadFactory threadFactory) -—— 且所有线程都使用ThreadFactory(线程工厂)来创建
package com.zhoulz.demo03;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
/**
* 测试ScheduledExecutorService接口中延迟执行任务和重复执行任务的功能
*/
public class ScheduledExecutorServiceDemo03 {
public static void main(String[] args) {
// 1、获取一个具备延迟执行任务的线程池对象
ScheduledExecutorService es = Executors.newSingleThreadScheduledExecutor( new ThreadFactory() {
int n = 1;
@Override
public Thread newThread(Runnable r) {
return new Thread(r,"自定义的线程名zlz:"+ n++);
}
});
// 2、创建多个任务对象,提交任务,每个任务延迟2秒执行
// 下面不再提交多个任务,而是就提交1个任务,并让其重复执行
// 初识延迟1秒,间隔2秒
es.scheduleWithFixedDelay(new MyRunnable3(666),1,2,TimeUnit.SECONDS);
System.out.println("over");
}
}
class MyRunnable3 implements Runnable{
private int id;
public MyRunnable3(int id) {
this.id = id;
}
@Override
public void run() {
String name = Thread.currentThread().getName();
// 模拟任务执行时间2秒,所以每间隔2+2=4秒后,才会有一次任务输出
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(name + "执行了任务:" + id);
}
}
结果:任务输出之间间隔了4秒。