- ScheduledThreadPoolExecutor继承自ThreadPoolExecutor。它主要用来在给定的延迟之后执行任务,或者定期执行任务。
- ScheduledThreadPoolExecutor的功能与Timer类似,但比Timer更强大,更灵活,Timer对应的是单个后台线程,而ScheduledThreadPoolExecutor可以在构造函数中指定多个对应的后台线程数。
1 创建ScheduledThreadPoolExecutor
- ScheduledThreadPoolExecutor通常使用工厂类Executors来创建,Executors可以创建两种类型的ScheduledThreadPoolExecutor,如下:
- (1)ScheduledThreadPoolExecutor:可以执行并行任务也就是多条线程同时执行。
- (2)SingleThreadScheduledExecutor:可以执行单条线程。
1.1 ScheduledThreadPoolExecutor
创建ScheduledThreadPoolExecutor的方法构造如下:
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize, ThreadFactory threadFactory)
1.2 SingleThreadScheduledExecutor
创建SingleThreadScheduledExecutor的方法构造如下:
public static ScheduledExecutorService newSingleThreadScheduledExecutor()
public static ScheduledExecutorService newSingleThreadScheduledExecutor(ThreadFactory threadFactory)
1.3 创建实例对象
创建实例对象代码如下
ScheduledExecutorService scheduledThreadPoolExecutor=Executors.newScheduledThreadPool(5);
ScheduledExecutorService singleThreadScheduledExecutor=Executors.newSingleThreadScheduledExecutor();
2 ScheduledThreadPoolExecutor执行机制分析
6b67d1561cfaa41a82514ca8b29056ed.png
分析:DelayQueue是一个无界队列,所以ThreadPoolExecutor的maximumPoolSize在ScheduledThreadPoolExecutor中无意义。
ScheduledThreadPoolExecutor的执行主要分为以下两个部分
- (1)当调用ScheduledThreadPoolExecutor的scheduleAtFixedRate()方法或者scheduleWithFixedDelay()方法时,会向ScheduledThreadPoolExecutor的DelayQueue添加一个实现了RunnableScheduledFuture接口的ScheduleFutureTask。
- (2)线程池中的线程从DelayQueue中获取ScheduleFutureTask,然后执行任务。
3 使用场景
3.1 ScheduledThreadPoolExecutor和SingleThreadScheduledExecutor的适用场景
- ScheduledThreadPoolExecutor:适用于多个后台线程执行周期性任务,同时为了满足资源管理的需求而需要限制后台线程数量的应用场景。
- SingleThreadScheduledExecutor:适用于需要单个后台线程执行周期任务,同时需要保证任务顺序执行的应用场景。
4 ScheduledThreadPoolExecutor使用案例
我们创建一个Runnable的对象,然后使用ScheduledThreadPoolExecutor的Scheduled()来执行延迟任务,输出执行时间即可:
4.1 该类延迟执行的方法:
public ScheduledFuture schedule(Runnable command,long delay, TimeUnit unit);
参数解析:
- command:就是一个实现Runnable接口的类
- delay:延迟多久后执行。
- unit:用于指定keepAliveTime参数的时间单位,这是一个枚举,常用的有TimeUnit.MILLISECONDS(毫秒),TimeUnit.SECONDS(秒)以及TimeUnit.MINUTES(分钟)等。
schedule
//创建一个工作线程继承Runnable
public class WorkerThread implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+" Start. Time = "+getNowDate());
threadSleep();
System.out.println(Thread.currentThread().getName()+" End. Time = "+getNowDate());
}
/**
* 睡3秒
*/
public void threadSleep(){
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 获取现在时间
*
* @return 返回时间类型 yyyy-MM-dd HH:mm:ss
*/
public static String getNowDate() {
Date currentTime = new Date();
SimpleDateFormat formatter;
formatter = new SimpleDateFormat ("yyyy-MM-dd HH:mm:ss");
String ctime = formatter.format(currentTime);
return ctime;
}
}
public class ScheduledThreadPoolTest {
public static void main(String[] args) {
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
try {
//schedule to run after sometime
System.out.println("Current Time = "+getNowDate());
for(int i=0; i<3; i++){
Thread.sleep(1000);
WorkerThread worker = new WorkerThread();
//延迟5秒后执行
scheduledThreadPool.schedule(worker, 10, TimeUnit.SECONDS);
}
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
scheduledThreadPool.shutdown();
while(!scheduledThreadPool.isTerminated()){
//wait for all tasks to finish
}
System.out.println("Finished all threads");
}
/**
* 获取现在时间
*
* @return 返回时间类型 yyyy-MM-dd HH:mm:ss
*/
public static String getNowDate() {
Date currentTime = new Date();
SimpleDateFormat formatter;
formatter = new SimpleDateFormat ("yyyy-MM-dd HH:mm:ss");
String ctime = formatter.format(currentTime);
return ctime;
}
}
9cc165d7ac247dbceff5524eb7faf2d8.png
线程任务确实在10秒延迟后才开始执行。这就是schedule()方法的使用。
** scheduleAtFixedRate**
public ScheduledFuture scheduleAtFixedRate(Runnable command,long initialDelay,long period,TimeUnit unit)
scheduleAtFixedRate方法的作用是预定在初始的延迟结束后,周期性地执行给定的任务,周期长度为period,其中initialDelay为初始延迟。
scheduleWithFixedDelay
public ScheduledFuture scheduleWithFixedDelay(Runnable command,long initialDelay,long delay,TimeUnit unit);
scheduleWithFixedDelay方法的作用是预定在初始的延迟结束后周期性地执行给定任务,在一次调用完成和下一次调用开始之间有长度为delay的延迟,其中initialDelay为初始延迟。
案例代码
//周期函数测试类
public class ScheduledTask {
public ScheduledThreadPoolExecutor se = new ScheduledThreadPoolExecutor(5);
public static void main(String[] args) {
new ScheduledTask();
}
public void fixedPeriodSchedule() {
// 设定可以循环执行的runnable,初始延迟为0,这里设置的任务的间隔为1秒
for(int i=0;i<5;i++){
se.scheduleAtFixedRate(new FixedSchedule(), 0, 1, TimeUnit.SECONDS);
}
}
public ScheduledTask() {
fixedPeriodSchedule();
}
class FixedSchedule implements Runnable {
public void run() {
System.out.println("当前线程:"+Thread.currentThread().getName()+" 当前时间:"+new Date(System.currentTimeMillis()));
}
}
}
SingleThreadScheduledExecutor的使用的方法基本是类似