Java并发之定时任务接口ScheduledExecutorService
来源:互联网 发布:计算机算法设计 网课 编辑:程序博客网 时间:2024/05/21 05:18
以前在使用Timer作为定时任务时,如果同时执行多个爬虫,且执行的时间过长,超过了两个爬虫的间隔时间,就会出现一些奇怪的错误,在查找了一些资料之后,这次来尝试下ScheduledExecutorService做为定时器,下面是简单的介绍。
java中要实现定时执行的方法通常有三种(这里不包括spring和一些已经实现好的工具类):
- 第一种就是创建一个线程然后一直循环通过sleep来达到定时执行,但是不容易控制任务的启动和取消
- 第二种就是使用Timer和TimerTask,这个使用起来相比第一种好了很多,但是做为单线程在处理多个任务和抛出异常的时候就不那么方便了
- 第三种ScheduledExecutorService是通常最理想的定时任务实现方式,主要将定时任务和线程池功能结合,能够更好的处理java中的一些并发的任务需要。
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) 方法用于安排指定的任务进行重复的固定速率执行,在指定的延迟后开始。参数说明如下:
- task:这是要被调度的任务
- delay:这是以毫秒为单位的延迟之后的任务执行
- period:这是在连续执行任务之间的毫秒的时间
在执行这个方法的时候会有两个异常要考虑:
- IllegalArgumentException–这个异常被抛出,如果time.getTime()为负。
- IllegalStateException–这将被抛出,如果任务已经安排或取消,计时器被取消,或者计时器线程已终止。
两种方法的区别:
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
- Java并发之定时任务接口ScheduledExecutorService
- java定时任务接口ScheduledExecutorService
- java定时任务接口ScheduledExecutorService
- java定时任务接口ScheduledExecutorService
- java定时任务接口ScheduledExecutorService
- java定时任务接口ScheduledExecutorService
- Java并发定时任务调度之Timer和ScheduledExecutorService
- 定时任务接口ScheduledExecutorService
- 【转】java定时任务接口ScheduledExecutorService
- Java定时任务接口ScheduledExecutorService代替Timer
- ScheduledExecutorService执行定时任务接口
- java使用ScheduledExecutorService定时任务
- Java 定时任务 ScheduledExecutorService 的使用
- Java并发编程:ScheduledExecutorService执行周期任务
- ScheduledExecutorService执行定时任务
- ScheduledExecutorService定时任务
- ScheduledExecutorService执行定时任务
- ScheduledExecutorService执行定时任务
- js模拟点击a标签,触发href
- error: insufficient permissions for device: verify udev rules
- Jenkins忘记账号密码
- 调用时编译器的优化问题
- 详细bitbucket入门手册,手把手操作指南
- Java并发之定时任务接口ScheduledExecutorService
- osx多用户设置共享文件夹(MacBook)
- mybatis学习笔记
- 网上资料汇总。。。
- 3.偏头痛杨的常见设计模式入门系列之工厂模式篇(简单+方法+抽象)
- BZOJ1858股票交易 单调队列优化DP
- react-native的WebView使用
- 广州富敦举办下午茶不仅是员工福利,更是情怀
- 最近项目中给图片添加水印老失败,报错信息如下