系列文章目录
关系图:
前言
ScheduledThreadPoolExecutor它与ThreadPoolExecutor最大的不同就是可以设置延迟任务和中期任务。
0.熟悉api
构造方法:
ScheduledThreadPoolExecutor(int corePoolSize)
指定核心线程大小,最大线程数默认为Integer.MAX_VALUE
ScheduledThreadPoolExecutor(int corePoolSize, RejectedExecutionHandler handler)
指定核心线程大小,最大线程数默认为Integer.MAX_VALUE并指定饱和策略
ScheduledThreadPoolExecutor(int corePoolSize, ThreadFactory threadFactory)
指定核心线程大小,最大线程数默认为Integer.MAX_VALUE并指定线程工厂
ScheduledThreadPoolExecutor(int corePoolSize, ThreadFactory threadFactory, RejectedExecutionHandler handler)
指定核心线程大小,最大线程数默认为Integer.MAX_VALUE并指定饱和策略和线程工厂
常用方法:
1.schedule方法
该方法可以用来延迟任务的执行
延迟执行任务一次:
public ScheduledFuture<?> schedule(
Runnable command,
long delay,
TimeUnit unit)
参数:
command:执行的任务
delay:延迟的时间
unit:枚举类,表示时间的单位可以是时分秒……
案例:
public class ScheduleThreadPoolExecutorTest {
public static void main(String[] args) {
System.out.println("当前系统时间"+System.currentTimeMillis());
//使用该构造方法默认最大核心线程数为Interger_Max
ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(5);
executor.schedule(new Runnable() {
@Override
public void run() {
System.out.println("开始执行时间"+System.currentTimeMillis());
}
},2, TimeUnit.SECONDS);
//延迟两秒再执行
executor.shutdown();
}
}
运行该程序时,你会发现先打印了当前系统时间,过了两秒后才打印出开始执行
2.固定频率执行任务
scheduleAtFixedRate()方法
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
long initialDelay,
long period,
TimeUnit unit);
参数:
command:执行的任务
initialDelay:首次执行的延迟时间
period:表示每次间隔的时间
unit:枚举类是上述两个时间的单位
案例:
import java.sql.SQLOutput;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class ScheduleThreadPoolExecutorTest {
public static void main(String[] args) {
System.out.println("2秒后开始打印当前时间"+getNowTime(System.currentTimeMillis()));
ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(100);
executor.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
System.out.println("当前时间"+getNowTime(System.currentTimeMillis()));
try {
//这里休眠是为了和后续的方法做比较
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},2,1,TimeUnit.SECONDS);
}
public static String getNowTime(Long time){
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(time);
}
}
打印结果:
3.固定的间隔时间执行任务
scheduleWithFixedDelay
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,
long initialDelay,
long period,
TimeUnit unit);
参数:
command:执行的任务
initialDelay:首次执行的延迟时间
period:表示每次间隔的时间
unit:枚举类是上述两个时间的单位
代码如下(示例):
import java.sql.SQLOutput;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class ScheduleThreadPoolExecutorTest {
public static void main(String[] args) {
System.out.println("2秒后开始打印当前时间"+getNowTime(System.currentTimeMillis()));
ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(100);
executor.scheduleWithFixedDelay(new Runnable() {
@Override
public void run() {
System.out.println("当前时间"+getNowTime(System.currentTimeMillis()));
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},2,1,TimeUnit.SECONDS);
}
public static String getNowTime(Long time){
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(time);
}
}
scheduleAtFixedRate和scheduleWithFixedDelay两者的区别
scheduleAtFixedRate的下一次执行时间是上一次执行时间+间隔时间
scheduleWithFixedDelay下一次执行时间是上一次执行时间结束时系统时间+间隔时间。
scheduleWithFixedDelay时间不固定但是周期固定
所以第一个案例下一次执行时间间隔了1秒,而第二个案例中每一次任务内部执行了1秒,所以下一次的执行时间就是2秒。
4.定时任务出现异常
如果说scheduleAtFixedRate和scheduleWithFixedDelay在执行时出现异常会怎么样?
案例:
import java.sql.SQLOutput;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class ScheduleThreadPoolExecutorTest {
public static void main(String[] args) {
System.out.println("2秒后开始打印当前时间"+getNowTime(System.currentTimeMillis()));
ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(100);
ScheduledFuture<?> scheduledFuture = executor.scheduleWithFixedDelay(new Runnable() {
@Override
public void run() {
System.out.println("当前时间" + getNowTime(System.currentTimeMillis()));
try {
Thread.sleep(1000);
//制造异常
int i = 2 / 0;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, 2, 1, TimeUnit.SECONDS);
}
public static String getNowTime(Long time){
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(time);
}
}
我们手动只要了一个异常:看一下结果
程序执行到异常的时候不在执行了。
当我们在使用ScheduledExecutorService接口的实现类处理任务的时候,如果一旦发生异常,就会被ScheduledExecutorService接口内部进行捕获。因此我们在发现程序不正确的时候需要即时查找原因。不然程序停止了也没有异常信息的打印。
5.取消定时任务的执行
我们在使用ScheduleThreadPoolExecutor执行任务时都会返回ScheduledFuture的。我们可以通过方法进行发送中断信号来取消定时任务
boolean cancel(boolean mayInterruptIfRunning)
试图取消对此任务的执行。
boolean isCancelled()
如果在任务正常完成前将其取消,则返回 true。
boolean isDone()
如果任务已完成,则返回 true。
案例:
5秒后取消定时任务:
import java.sql.SQLOutput;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class ScheduleThreadPoolExecutorTest {
public static void main(String[] args) {
System.out.println("2秒后开始打印当前时间"+getNowTime(System.currentTimeMillis()));
ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(100);
ScheduledFuture<?> scheduledFuture = executor.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
System.out.println("当前时间" + getNowTime(System.currentTimeMillis()));
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, 2, 1, TimeUnit.SECONDS);
try {
Thread.sleep(5000);
//取消定时任务
scheduledFuture.cancel(true);
if(scheduledFuture.isDone()){
System.out.println("任务完成");
}
if(scheduledFuture.isCancelled()){
System.out.println("任务取消");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static String getNowTime(Long time){
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(time);
}
}
结果: