Java定时任务ScheduledThreadPoolExecutor
采用ScheduledThreadPoolExecutor执行定时重试任务时内存溢出的分析及解决

采用ScheduledThreadPoolExecutor执行定时重试任务时内存溢出的分析及解决作者:余志坚姜春志来源:《科技资讯》2016年第07期摘要:开发JavaWeb项目中发现服务之间的调用存在超时情况,由于涉及的处理逻辑全部是异步,引入定时重试的机制,重试工具选择了JDK自带的ScheduledThreadPoolExecutor。
当A服务依赖B服务,B服务由于在业务高峰期处理能力降低,导致大量A服务过来的请求超时,A加入了超时重试机制,间隔时间根据重试次数的多少来决定,次数越多,两次重试之间间隔的时间越多,此时的业务高峰也会给A带来大量请求,大量的超时会导致重试队列迅速堆积,直到内存溢出。
该文从线程池工作机制、ScheduledThreadPoolExecutor实例的创建,获取重试任务的过程以及提交任务的过程角度分析,并通过源代码的剖析和测试工具MyEclipse进行演示测试内存泄露的情况,得出避免内存泄露的解决方案。
关键词:ScheduledThreadPoolExecutor 线程池内存溢出中图分类号:TP3 文献标识码:A 文章编号:1672-3791(2016)03(a)-0015-031 ScheduledThreadPoolExecutor实例的创建过程及线程池工作机制1.1 ScheduledThreadPoolExecutor实例的创建过程重试工具选择了JDK自带的ScheduledThreadPoolExecutor。
ScheduledThreadPoolExecutor 实例的创建过程如下:ScheduledThreadPoolExecutor实例的创建过程如下:(1)获取当前机器上处理器的数量;(2)使用Google的ThreadFactoryBuiler创建指定格式名称的线程,以方便查看问题;(3)有需要被拒绝的任务时,抛出异常;(4)创建定时任务池;打开MyEclipse 工具显示相对的代码:int corePoolSize=Runtime.getRuntime().availableProcessors();ThreadFactory tf=new ThreadFactoryBuilder().setNameFormat("FailureRetryTask-pool-%d").build();RejectedExecutionHandler handler=new ThreadPoolExecutor.AbortPolicy();ScheduledThreadPoolExecutor taskService=new ScheduletThreadPooExecutor(corePoolSize,tf,handler);线程池就是多个线程在一个队列中取任务执行,提交的任务会被放入队列中等待线程执行,故队列要设置一个大小。
java scheduledthreadpoolexecutor cron表达式 -回复

java scheduledthreadpoolexecutor cron表达式-回复Java中的ScheduledThreadPoolExecutor是一个用于调度任务的线程池,它允许根据cron表达式指定任务的执行时间。
本文将详细介绍cron表达式的语法和使用方法,并且提供一些实际示例来帮助读者更好地理解和应用cron表达式。
# 1. 什么是cron表达式cron表达式是一种用于指定任务执行时间的时间表达式,它有6个或7个字段组成,每个字段代表时间的一个部分。
这些字段的排列顺序分别是:秒(0-59)、分(0-59)、小时(0-23)、日期(1-31)、月份(1-12)、星期(0-7,其中0和7表示星期天)和年份(可选)。
# 2. cron表达式的语法cron表达式的语法由各个字段的取值规定,下面是cron表达式的基本语法:1 2 3 4 5 6 7字段的取值规则如下:- 字段1(秒):0-59的整数- 字段2(分):0-59的整数- 字段3(小时):0-23的整数- 字段4(日期):1-31的整数(有些特殊的月份日期可能无效)- 字段5(月份):1-12的整数- 字段6(星期):0-7的整数或者英文缩写(0和7表示星期天,1表示星期一,以此类推)- 字段7(年份,可选):1970-2099的整数# 3. cron表达式的使用示例现在我们来看一些具体的cron表达式示例,以帮助读者更好地理解和使用cron表达式。
示例1:每分钟执行一次* * * * * *这个cron表达式表示每分钟执行一次。
示例2:每天的10点和22点执行一次0 0 10,22 * * *这个cron表达式表示在每天的10点和22点都会执行一次。
示例3:在每月的第2个星期一的上午10点执行一次0 0 10 ? * 2#2 *这个cron表达式表示在每月的第2个星期一的上午10点执行一次。
# 4. 使用ScheduledThreadPoolExecutor执行任务在Java中,我们可以使用ScheduledThreadPoolExecutor来按照cron 表达式执行任务。
java定时器线程池(ScheduledThreadPoolExecutor)的实现

java定时器线程池(ScheduledThreadPoolExecutor)的实现前⾔定时器线程池提供了定时执⾏任务的能⼒,即可以延迟执⾏,可以周期性执⾏。
但定时器线程池也还是线程池,最底层实现还是ThreadPoolExecutor,可以参考我的另外⼀篇⽂章多线程–精通ThreadPoolExecutor。
特点说明1.构造函数public ScheduledThreadPoolExecutor(int corePoolSize) {// 对于其他⼏个参数在ThreadPoolExecutor中都已经详细分析过了,所以这⾥,将不再展开// 这⾥我们可以看到调⽤基类中的⽅法时有个特殊的⼊参DelayedWorkQueue。
// 同时我们也可以发现这⾥并没有设置延迟时间、周期等参数⼊⼝。
// 所以定时执⾏的实现必然在DelayedWorkQueue这个对象中了。
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,new DelayedWorkQueue());}2.DelayedWorkQueueDelayedWorkQueue是在ScheduledThreadPoolExecutor的⼀个内部类,实现了BlockingQueue接⼝⾥⾯存放任务队列的数组如下:private RunnableScheduledFuture<?>[] queue =new RunnableScheduledFuture<?>[INITIAL_CAPACITY];我们分析过ThreadPoolExecutor,它从任务队列中获取任务的⽅式为poll和take两种,所以看⼀下poll和take两个⽅法的源码,回顾⼀下,ThreadPoolExecutor它会调⽤poll或take⽅法,先poll,再take,只要其中⼀个接⼝有返回就⾏public RunnableScheduledFuture<?> poll() {final ReentrantLock lock = this.lock;lock.lock();try {RunnableScheduledFuture<?> first = queue[0];// 这⾥有个getDelay,这是关键点,获取执⾏延时时间// 但是如果我们有延时设置的话,这就返回空了,然后就会调⽤take⽅法if (first == null || first.getDelay(NANOSECONDS) > 0)return null;elsereturn finishPoll(first);} finally {lock.unlock();}}public RunnableScheduledFuture<?> take() throws InterruptedException {final ReentrantLock lock = this.lock;lock.lockInterruptibly();try {for (;;) {RunnableScheduledFuture<?> first = queue[0];if (first == null)available.await();else {// 获取延时时间long delay = first.getDelay(NANOSECONDS);if (delay <= 0)return finishPoll(first);first = null; // don't retain ref while waitingif (leader != null)available.await();else {Thread thisThread = Thread.currentThread();leader = thisThread;try {// 使⽤锁,执⾏延时等待。
JAVA定时器的三种方法(详细注解)

JAVA定时器的三种方法(详细注解)在Java中,有三种主要的定时器方法可以实现任务的定时执行。
这些方法包括Timer类、ScheduledThreadPoolExecutor类和TimerTask类。
下面将详细介绍这三种定时器方法的使用。
1. Timer类:Timer类是Java提供的一个基本的定时器类,可以用于在指定的时间间隔内执行指定的任务。
Timer类提供了schedule(和scheduleAtFixedRate(两个方法,用于按照指定的时间间隔执行任务。
(1)schedule(方法:该方法用于在指定的时间间隔后执行任务。
它的语法如下:public void schedule(TimerTask task, long delay)参数task表示要执行的任务,它是一个实现了TimerTask接口的类的实例。
参数delay表示延迟的时间,以毫秒为单位。
例如,下面的代码使用Timer类的schedule(方法,在延迟2秒后执行一个任务:```public void ruSystem.out.println("任务执行了");}},2000);```当运行上述代码后,程序将会输出"任务执行了"。
(2)scheduleAtFixedRate(方法:该方法用于以固定的时间间隔执行任务。
它的语法如下:public void scheduleAtFixedRate(TimerTask task, long delay, long period)参数task表示要执行的任务,它是一个实现了TimerTask接口的类的实例。
参数delay表示延迟的时间,以毫秒为单位。
参数period表示每次任务执行间隔的时间,也是以毫秒为单位。
例如,下面的代码使用Timer类的scheduleAtFixedRate(方法,延迟2秒后开始执行一个任务,并且每隔1秒执行一次:```public void ruSystem.out.println("任务执行了");}},2000,1000);```当运行上述代码后,程序将会输出"任务执行了",并且每隔1秒输出一次。
newscheduledthreadpool 使用方法

newscheduledthreadpool 使用方法(实用版4篇)目录(篇1)1.新建 ScheduledThreadPool2.创建 ScheduledFuture3.启动 ScheduledThreadPool4.关闭 ScheduledThreadPool5.示例代码正文(篇1)在新的 Java 程序中,我们常常需要定时执行某些任务,例如定时打印日志、定时更新数据等。
这时,我们可以使用 Java 提供的ScheduledThreadPool 来实现。
下面将详细介绍如何使用ScheduledThreadPool。
首先,我们需要新建一个 ScheduledThreadPool。
这个线程池是线程安全的,并且允许我们安排定期执行的任务。
创建方法如下:```javaScheduledThreadPool scheduledThreadPool =Executors.newScheduledThreadPool(1);```接下来,我们需要创建一个 ScheduledFuture。
这个对象用于表示计划中的任务,以及任务的执行时间。
创建方法如下:```javaScheduledFuture<?> scheduledFuture =scheduledThreadPool.schedule(new Runnable() {@Overridepublic void run() {// 在这里编写你的任务代码}}, 0, 1000); // 参数分别为:延迟时间、周期时间、任务代码```其中,延迟时间为 0,表示任务立即执行;周期时间为 1000,表示任务每隔 1000 毫秒执行一次。
接着,我们可以启动 ScheduledThreadPool。
这一步通常是多余的,因为 ScheduledThreadPool 会在创建时自动启动。
```javascheduledThreadPool.start();```当我们不再需要 ScheduledThreadPool 时,应该将其关闭。
java延时执行方法

java延时执行方法在Java中,可以使用多种方法来实现延时执行某个方法。
下面我将介绍三种常见的方法:使用Thread.sleep()方法、使用Timer定时器、使用ScheduledThreadPoolExecutor线程池。
首先,我们可以使用Thread.sleep()方法来实现延时执行某个方法。
Thread.sleep()方法是一个静态方法,可以让当前线程暂停执行指定的时间。
例如,要延时执行某个方法3秒钟,可以使用如下代码:javatry {Thread.sleep(3000); 暂停3秒钟调用需要延时执行的方法} catch (InterruptedException e) {e.printStackTrace();}这种方法简单直接,但是必须手动处理异常,并且会阻塞当前线程的执行。
其次,我们可以使用Timer定时器来实现延时执行某个方法。
Timer类是Java 提供的一个简单的定时器工具类,可以用来调度自定义任务的执行。
例如,要延时执行某个方法3秒钟,可以使用如下代码:javaTimer timer = new Timer();timer.schedule(new TimerTask() {@Overridepublic void run() {调用需要延时执行的方法}}, 3000);这种方法使用起来相对方便,可以设置任务的延时执行时间,但是不支持取消任务的执行。
最后,我们可以使用ScheduledThreadPoolExecutor线程池来实现延时执行某个方法。
ScheduledThreadPoolExecutor类是Java提供的一个可定时执行任务的线程池,可以设置任务的延时执行时间和周期执行时间。
该类实现了ScheduledExecutorService接口,提供了比Timer更灵活、更健壮的定时任务执行功能。
例如,要延时执行某个方法3秒钟,可以使用如下代码:javaScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1);executor.schedule(new Runnable() {@Overridepublic void run() {调用需要延时执行的方法}}, 3, TimeUnit.SECONDS);executor.shutdown();这种方法可以设置任务的延时执行时间和周期执行时间,还可以取消任务的执行。
scheduledthreadpoolexecutor的基本使用

scheduledthreadpoolexecutor的基本使用scheduledThreadPoolExecutor是Java中的一个线程池Executor的实现类,它可以按照一定的调度策略来执行定时任务。
本文将详细介绍scheduledThreadPoolExecutor的基本使用方法,包括创建和初始化、任务调度和取消、线程池的生命周期管理等方面。
# 一、创建和初始化scheduledThreadPoolExecutor在开始使用scheduledThreadPoolExecutor之前,我们首先需要导入相应的包:javaimport java.util.concurrent.Executors;import java.util.concurrent.ScheduledExecutorService;import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit;接下来,我们可以通过以下代码创建并初始化一个scheduledThreadPoolExecutor对象:javaScheduledExecutorService scheduledThreadPoolExecutor = Executors.newScheduledThreadPool(5);在上述代码中,我们使用Executors类的`newScheduledThreadPool`方法创建了名为scheduledThreadPoolExecutor的scheduledThreadPoolExecutor对象,该对象将维护一个包含5个线程的线程池。
# 二、任务调度和取消scheduledThreadPoolExecutor提供了多种方法来安排任务的执行,以下是其中几种常用的方法:方法一:scheduleschedule方法用于安排一个一次性的任务,接受三个参数:待执行的任务、延迟执行的时间和时间单位。
scheduledthreadpoolexecutor 条件判断结束任务

scheduledthreadpoolexecutor 条件判断结束任务scheduledThreadPoolExecutor 条件判断结束任务简介:scheduledThreadPoolExecutor 是Java 中的一个线程池,它可以以定时任务的方式执行任务。
它继承了ThreadPoolExecutor 类,并扩展了一些功能,使得任务的执行变得更加灵活和方便。
本文将介绍如何在scheduledThreadPoolExecutor 中进行条件判断并结束任务。
第一步:创建scheduledThreadPoolExecutor 对象首先,我们需要创建一个scheduledThreadPoolExecutor 对象。
可以通过调用Executors 类的静态方法newScheduledThreadPool 来创建scheduledThreadPoolExecutor 对象,指定线程池的大小。
javaScheduledExecutorService executorService =Executors.newScheduledThreadPool(5);上述代码创建了一个线程池,大小为5,即最多同时执行5个任务。
第二步:创建一个实现Runnable 接口的任务类然后,我们需要创建一个实现Runnable 接口的任务类,这个类中包含需要执行的任务逻辑。
javaclass MyTask implements Runnable {public void run() {任务逻辑}}在这个任务类中,我们可以编写具体的任务逻辑代码,在run 方法中定义需要执行的任务。
第三步:判断条件并结束任务接下来,我们需要对条件进行判断,并根据条件来结束任务。
在线程池中执行定时任务时,可以使用schedule 方法来调度任务的执行时间,并使用cancel 方法来结束任务。
javaScheduledFuture<?> future = executorService.schedule(newMyTask(), 5, TimeUnit.SECONDS);if (condition) {future.cancel(true);}上述代码中,我们使用schedule 方法调度了一个任务执行时间为5秒后执行,并将返回的ScheduledFuture 对象保存起来。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Timer计时器有管理任务延迟执行("如1000ms后执行任务")以及周期性执行("如每500ms执行一次该任务")。
但是,Timer存在一些缺陷,因此你应该考虑使用ScheduledThreadPoolExecutor作为代替品,Timer对调度的支持是基于绝对时间,而不是相对时间的,由此任务对系统时钟的改变是敏感的;ScheduledThreadExecutor只支持相对时间。
Timer的另一个问题在于,如果TimerTask抛出未检查的异常,Timer将会产生无法预料的行为。
Timer线程并不捕获异常,所以TimerTask抛出的未检查的异常会终止timer 线程。
这种情况下,Timer也不会再重新恢复线程的执行了;它错误的认为整个Timer都被取消了。
此时,已经被安排但尚未执行的TimerTask永远不会再执行了,新的任务也不能被调度了。
例子:packagecom.concurrent.basic;importjava.util.Timer;import java.util.TimerTask;public class TimerTest {private Timer timer = new Timer();// 启动计时器public void lanuchTimer() {timer.schedule(new TimerTask() {public void run() {throw new RuntimeException();}}, 1000 * 3, 500);}// 向计时器添加一个任务public void addOneTask() {timer.schedule(new TimerTask() {public void run() {System.out.println("hello world");}}, 1000 * 1, 1000 * 5);}public static void main(String[] args) throws Exception {TimerTest test = new TimerTest();nuchTimer();Thread.sleep(1000 * 5);// 5秒钟之后添加一个新任务test.addOneTask();}}执行结果:你可能希望第二个没有异常的线程会一直运行下去,然而实际情况如程序所示5秒钟后就中止了,还伴随着一个异常,异常的消息是"Timer already cancelled"。
ScheduledThreadPoolExector妥善地处理了这个异常的任务,所以说在java5.0或更高的JDK中,几乎没有理由再使用Timer了。
java5.0后提供public interface ScheduledExecutorServiceextends ExecutorService一个ExecutorService,可安排在给定的延迟后运行或定期执行的命令。
schedule方法使用各种延迟创建任务,并返回一个可用于取消或检查执行的任务对象。
scheduleAtFixedRate和scheduleWithFixedDelay方法创建并执行某些在取消前一直定期运行的任务。
而且不受时钟限制。
例子:package com.concurrent.basic;import java.util.concurrent.Executors;import java.util.concurrent.ScheduledExecutorService;import java.util.concurrent.TimeUnit;public class ScheduledExecutorTest {//线程池能按时间计划来执行任务,允许用户设定计划执行任务的时间,int类型的参数是设定//线程池中线程的最小数目。
当任务较多时,线程池可能会自动创建更多的工作线程来执行任务public ScheduledExecutorService scheduExec =Executors.newScheduledThreadPool(1);//启动计时器public void lanuchTimer(){Runnable task = new Runnable() {public void run() {throw new RuntimeException();}};scheduExec.scheduleWithFixedDelay(task, 1000*5, 1000*10,LISECONDS);}//添加新任务public void addOneTask(){Runnable task = new Runnable() {public void run() {System.out.println("welcome to china");}};scheduExec.scheduleWithFixedDelay(task, 1000*1, 1000,LISECONDS);}public static void main(String[] args) throws Exception { ScheduledExecutorTest test = new ScheduledExecutorTest();nuchTimer();Thread.sleep(1000*5);//5秒钟之后添加新任务test.addOneTask();}}但是ScheduledThreadPoolExecutor也有不利的地方,就是只能按相对的时间的,而不能设置具体某个时刻之后执行,如每天晚上12点定时执行任务之类的要求使用Timer更合适,如果是周期性的重复工作可以考虑使用ScheduledThreadPoolExecutor。
Java定时任务ScheduledThreadPoolExecutor2012-08-05 13:15:00以前定时任务一直用Timer这个类,后来发现ScheduledThreadPoolExecutor功能更强大,我们先看个简单的示例,然后再看看API中的描述:这个定时任务是我的项目中,每隔5分钟去检查设备的在线状态的。
[java]public class CheckDeviceStateExcuter {private static final Log log =LogFactory.getLog(CheckDeviceStateExcuter.class);private static final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);private static DeviceDaodeviceDao = new DeviceDaoImpl();private static List<DeviceDTO> devices = newArrayList<DeviceDTO>();// invoke DLL method to get the details of devicestatic JoymindCommDLLLib instance =JoymindCommDLLLib.INSTANCE;// check statespublic static void checkStart() {final Runnable checker = new Runnable() {public void run() {System.out.println("check");devices = deviceDao.queryDevices();for(DeviceDTO device : devices){String ip = device.getIp();String id = "auto_refresh_" + ip;String iniPath = XmlOperationTool.PLAYLIST_TEMPFILE_FOLDER + id+ ".ini";int flag = instance.GetSysInfo(ip, iniPath);if(flag == 1){// get ini fileSystemInfoDTO info = null;try {info = FileOperationTool.parseIni(iniPath);device.setMacAdd(info.getMacAddress()); device.setIp(info.getIp());device.setGateway(info.getGateway()); device.setOnlineState("在线");device.setBootTime(info.getBootTime()); device.setDeviceVersion(info.getVersion()); device.setAvailableSpace(info.getFreedisk());device.setpNo(info.getpNo());device.setWidth(info.getWidth());device.setHeight(info.getHeight());device.setStorage(info.getStorage()); device.setTime(info.getTime());device.setPrgTotal(info.getPrgTotal()); device.setPrgIndex(info.getPrgIndex()); device.setStatusNo(info.getStatus());if (info.getStorage().equals("1")) {device.setStorageName("FLASH存储");}if (info.getStorage().equals("2")) {device.setStorageName("RAM存储");}if (info.getStorage().equals("3")) {device.setStorageName("SD卡存储");}device.setCurrentPlaylist("");device.setCurrentTemplate("");device.setLastCommunicateTime(""); device.setCurrentTransferFileName(""); device.setCurrentTransferSpeed("");device.setCurrentPercentage("");device.setVolume("");device.setAutoBootTime("");device.setAutoShutdownTime("");device.setPlayingVideo("");device.setProgramUpdateTime("");device.setProgramUpdateState("");} catch (IOException e1) {if (log.isErrorEnabled()) {log.error(e1.getMessage());}e1.printStackTrace();}booleanaddFlag = deviceDao.updateDevice(device);if (addFlag) {if (log.isDebugEnabled()) {log.debug("auto update device "+device.getName()+" successfully"); }} else {if (log.isErrorEnabled()) {log.error("auto update device failed !!!");}}}else{deviceDao.updateDevice(ip, "离线");if (log.isDebugEnabled()) {log.debug("auto update device "+device.getName()+" statue offline"); }}}}};// 此处的checker是一个线程,1表示启动延迟1个单位开始执行这个线程,然后每隔5分钟执行一次,单位是分钟final ScheduledFuture<?>checkerHandle =scheduler.scheduleAtFixedRate(checker, 1, 5, TimeUnit.MINUTES);// 这里注释的地方是取消这个定时任务的,是在3600天后停止,因为我这里是检查设备的,所以除非当程序退出才自动停止这个定时任务/*scheduler.schedule(new Runnable() {public void run() {checkerHandle.cancel(true);}}, 60 * 60, TimeUnit.DAYS);*/}/*** @paramargs*/public static void main(String[] args) {// TODO Auto-generated method stub}再看看API的具体信息,总之这是个非常实用的类public class ScheduledThreadPoolExecutorextends ThreadPoolExecutorimplements ScheduledExecutorServiceThreadPoolExecutor,它可另行安排在给定的延迟后运行命令,或者定期执行命令。