赞
踩
以前在使用Timer作为定时任务时,如果同时执行多个爬虫,且执行的时间过长,超过了两个爬虫的间隔时间,就会出现一些奇怪的错误,在查找了一些资料之后,这次来尝试下ScheduledExecutorService做为定时器,下面是简单的介绍。
java中要实现定时执行的方法通常有三种(这里不包括spring和一些已经实现好的工具类):
ScheduledExecutorService,是基于线程池设计的定时任务类,每个调度任务都会分配到线程池中的一个线程去执行,也就是说,任务是并发执行,互不影响。需要注意,只有当调度任务来的时候,ScheduledExecutorService才会真正启动一个线程,其余时间ScheduledExecutorService都是出于轮询任务的状态。
首先是一个简单的例子:
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class Test{
public static void main(String[] args) {
Runnable runnable = new Runnable() {
//所要定时执行的任务
public void run() {
System.out.println("Hello !!");
}
};
ScheduledExecutorService service = Executors
.newSingleThreadScheduledExecutor();
// 第二个参数为首次执行的延时时间,第三个参数为定时执行的间隔时间(下面有解释这两种方法的区别)
service.scheduleAtFixedRate(runnable, 10, 1, TimeUnit.SECONDS);
servuce.scheduleWithFixedDelay(runnable, 10, 1,TimeUnit.SECONDS);
}
}
这里创建任务是使用Runnable接口,在程序开发中只要是多线程肯定永远以实现Runnable接口为主,因为实现Runnable接口相比继承Thread类有如下好处:
其中scheduleAtFixedRate(TimerTask task,long delay,long period) 方法用于安排指定的任务进行重复的固定速率执行,在指定的延迟后开始。参数说明如下:
在执行这个方法的时候会有两个异常要考虑:
ScheduledExecutorService 中两种最常用的调度方法 ScheduleAtFixedRate 和 ScheduleWithFixedDelay。
ScheduleAtFixedRate 每次执行时间为上一次任务开始起向后推一个时间间隔,即每次执行时间为 :initialDelay,
initialDelay+period, initialDelay+2*period, …;
ScheduleWithFixedDelay每次执行时间为上一次任务结束起向后推一个时间间隔,即每次执行时间为:initialDelay,
initialDelay+executeTime+delay, initialDelay+2*executeTime+2*delay。
由此可见,ScheduleAtFixedRate 是基于固定时间间隔进行任务调度,ScheduleWithFixedDelay 取决于每次任务执行的时间长短,是基于不固定时间间隔进行任务调度
程序有时候要求任务在每天的某一个时刻运行,下面是我自己写的一个列子,供参考:
import java.text.ParseException;
import java.util.Date;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
* Created by gray- on 2017/10/25.
*
*
* 测试java中并发的ScheduledExecutorService 的定时效果
*
*
* 它具有以下的好处:
* 1、相比于Timer的单线程,它是通过线程池的方式来执行任务的
* 2、可以很灵活的去设定第一次执行任务delay的时间
* 3、提供了更好的约定,以便设定执行的时间间隔
*/
public class ScheduledExecutorServiceTest {
public static void main(String[] args){
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("hello!!!");
}
};
//在每天的下午五点半运行
long oneDay = 60 * 60 * 24 * 1000;
long initDelay = getTimeMillis("17:30:00") - System.currentTimeMillis();
initDelay = initDelay>0? initDelay : oneDay + initDelay;
ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
service.scheduleAtFixedRate(runnable, initDelay , oneDay, TimeUnit.MILLISECONDS);
}
public static long getTimeMillis(String time){
DateFormat dateFormat = new SimpleDateFormat("yy-MM-dd HH:mm:ss");
DateFormat dayFormat = new SimpleDateFormat("yy-MM-dd");
try {
Date curDate = dateFormat.parse(dayFormat.format(new Date()) + " " + time);
return curDate.getTime();
} catch (ParseException e) {
e.printStackTrace();
}
return 0;
}
}
以上就是对ScheduledExecutorService的简单的了解,要想深入理解可以直接看源码,
这里分享一篇介绍源码的文章:http://www.cnblogs.com/sunxucool/archive/2013/06/21/3148141.html
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。