scheduleatfixedrate运用Executors.newScheduledThreadPool的任务调度怎么解决

scheduleatfixedrate  时间:2021-05-30  阅读:()

如何使activity显示一段时间自动跳转另一个activity?

ScheduledExecutorService timer = Executors.newScheduledThreadPool(1); timer.scheduleAtFixedRate(new Runnable() { @Override public void run() { //TODO:skip to the next activity } }, 5, //第一次开始的延迟时间 5,//每隔5秒执行 TimeUnit.SECONDS);//时间单位为秒 }

如何正确使用Timer

在需要按时间计划执行简单任务的情况下,Timer是最常被使用到的工具类。

使用Timer来调度TimerTask的实现者来执行任务,有两种方式,一种是使任务在指定时间被执行一次,另一种是从某一指定时间开始周期性地执行任务。

下面是一个简单的Timer例子,它每隔10秒钟执行一次特定操作doWork。

Timer timer = new Timer(); TimerTask task = new TimerTask (){ public void run() { doWork(); } }; timer.schedule (task, 10000L, 10000L); 可以看到,具体的任务由TimerTask的子类实现,Timer负责管理、执行TimerTask。

Timer 的使用 在不同的场景下,需要使用不同的Timer接口。

如上所说,主要区分两种情况 1) 在指定时间执行任务,只执行一次 - public void schedule(TimerTask task, long delay) - public void schedule(TimerTask task, Date time) 2)从指定时间开始,周期性地重复执行,直到任务被cancel掉。

其中又分两种类型: 2.1) 一种是按上一次任务执行的时间为依据,计算本次执行时间,可以称为相对时间法。

比如,如果第一次任务是1分10秒执行的,周期为5秒,因系统繁忙(比如垃圾回收、虚拟内存切换),1分15秒没有得到机会执行,直到1分16秒才有机会执行第二次任务,那么第3次的执行时间将是1分21秒,偏移了1秒。

- public void schedule(TimerTask task, long delay, long period) - public void schedule(TimerTask task, Date firstTime, long period) 2.2) 另一种是绝对时间法,以用户设计的起始时间为基准,第n次执行时间为“起始时间+n*周期时间”。

比如,在上面的情况下,虽然因为系统繁忙,第二执行时间被推后1秒,但第3次的时间点仍然应该是1分20秒。

- public void scheduleAtFixedRate(TimerTask task, long delay, long period) - public void scheduleAtFixedRate(TimerTask task, Date firstTime, long period) 相对时间法,关注于满足短时间内的执行间隔,绝对时间法,则更关注在一个长时间范围内,任务被执行的次数。

如果我们要编写一个程序,用timer控制文档编辑器中提示光标的闪烁,用哪种更合适? 当然是相对时间法。

如果改用绝对时间法,当从系统繁忙状态恢复后,光标会快速连续闪烁多次,以弥补回在系统繁忙期间没有被执行的任务,这样的情况会用户来说比较难以接受。

又如,每10分钟检查一次新邮件的到来,也适合于使用相对时间法。

Timer timer = new Timer(); TimerTask task = new TimerTask (){ public void run() { displayCursor(); } }; timer.schedule (task, 1000L, 1000L); //每秒闪烁一次光标 作为对比,我们来考虑一种绝对时间法的应用场景——倒数任务,比如,要求在10秒内做倒数计时,每秒做一次doworkPerSecond操作,10秒结束时做一次doworkEnd操作,然后结束任务。

Timer timer = new Timer(); TimerTask task = new TimerTask (){ private int count=10; public void run() { if(count>0){ doWorkPerSecond(); count--; }else{ doWorkEnd(); cancel(); } } }; timer. scheduleAtFixedRate (task, 1000L, 1000L); Timer及相关类的内部实现 - Timer的内部会启动一个线程TimerThread。

即使有多个任务被加入这个Timer,它始终只有一个线程来管理这些任务。

- TimerThread是Thread的子类。

加入Timer的所有任务都会被最终放入TimerThread所管理的TaskQueue中。

TimerThread会不断查看TaskQueue中的任务,取出当前时刻应该被执行的任务执行之,并且会重新计算该任务的下一次执行时间,重新放入TaskQueue。

直到所有任务执行完毕(单次任务)或者被cancel(重复执行的任务),该线程才会结束。

- TaskQueue,由数组实现的二叉堆,堆的排序是以任务的下一次执行时间为依据的。

二叉堆的使用使得TimerThread以简洁高效的方式快速找到当前时刻需要执行的TimerTask,因为,堆排序的特性是保证最小(或者最大)值位于堆叠顶端,在这里,queue[1]始终是下次执行时间(nextExecutionTime)最小的,即应该最先被执行的任务 比如,同一个timer管理两个任务task1和task2 timer.schedule (task1, 4000L, 10000L); timer. scheduleAtFixedRate (task2, 2000L, 15000L); 则,TaskQueue中会有两个任务:task1和task2。

task2会排在头部queue[1],当task2执行时间到,task2被执行,同时修改其nextExecutionTime =当前的nextExecutionTime +15000L(绝对时间法)并重新在二叉堆中排序。

排序后,task1被放到头部。

当task1执行时间到,task1被执行,并修改其nextExecutionTime =当前时间+10000L,然后重新在二叉堆中对其排序……… 一个例子 当收到客户端请求时,服务端生成一个Response对象。

服务端希望客户端访问该对象的间隔时间不能超过20秒,否则,服务端认为客户端已经异常关闭或者网络异常,此时销毁掉该对象并打印错误日志。

每次访问都会重新开始计时。

class Response{ private TimerTask timeout; public void init(){ ……… Timer timer = new Timer(); timeout = new TimeOutTask(); timer.schedule (timeout, 20000L); } public void invoke(){ timeout.cancel();//取消当前的timeout任务 …. timeout = new TimeOutTask(); timer.schedule (timeout, 20000L);//重新开始计时 } void destroy(){ …….. } class TimeOutTask extends TimerTask{ public void run() { TraceTool.error(“Time out, destroy the Response object.”); destroy(); } } } 因为Timer不支持对任务重置计时,所以此处采取了先cancel当前的任务再重新加入新任务来达到重置计时的目的。

注意,对一个已经cancel的任务,不能通过schedule重新加入Timer中执行。

TimerTask的状态机如下: 一个新生成的TimerTask其状态为VIRGIN,Timer只接受状态为VIRGIN的任务,否则会有IllegalStateException异常抛出。

调用任务的cancel方法,该任务就转入CANCELLED状态,并很快从TaskQueue中删除。

对单次执行的任务,一旦执行结束,该任务也会从中删除。

这意味着TimerTask将不再被timer所执行了。

关于java定时器Timer的疑问,当执行时间大于间隔时间会怎样?

看用了timer的哪个方法了。

schedule 方法的话就是任务执行完以后再等待你指定的间隔时间后 再次执行。

scheduleAtFixedRate 方法的话就是等当前执行的任务完成后立刻再次执行任务

java timer wait函数怎么用

Timer 是一种定时器工具,用来在一个后台线程计划执行指定任务,这些任务可以被执行一次,也可以被定期执行。

每个 Timer 对象对应一个后台线程,顺序地执行所有计时器任务。

如果完成某个计时器任务的时间太长,那么它会“独占”计时器的任务执行线程,从而可能延迟后续任务的执 行。

对 Timer 对象最后的引用完成并且所有未处理的任务都已执行完成后,计时器的任务执行线程会正常终止(并且成为垃圾回收的对象)。

TimerTask是一个抽象类, 实现了Runable接口,它的子类代表一个可以被Timer计划的任务。

1) 一个简单的Demo,让大家对Timer、TimerTask的使用有感性的认识。

2) Timer和TimerTask的常用api函数说明 这里强调Timer类的schedule和scheduleAtFixedRate的区别。

schedule和 scheduleAtFixedRate的区别在于,schedule以固定的相对时间间隔执行,如果某一次执行被延时了,往后的执行的执行时间也会相对 延时;而scheduleAtFixedRate是以绝对的时间间隔执行,如果某一次执行被延时,它的后一次执行的延时将会缩短 (scheduleAtFixedRate会把已经过去的时间也作为周期执行)。

schedule注重的是时间间隔的稳定,而 scheduleAtFixedRate注重的是执行频率的稳定。

3) Timer的终止 默认情况下,只要一个程序的timer线程在运行,那么这个程序就会保持运行。

当然,你可以通过以下四种方法终止一个timer线程: a)调用timer的cancle方法。

你可以从程序的任何地方调用此方法,甚至在一个timer task的run方法里; b)让timer线程成为一个daemon线程(可以在创建timer时使用new Timer(true)达到这个目地),这样当程序只有daemon线程的时候,它就会自动终止运行; c)当timer相关的所有task执行完毕以后,删除所有此timer对象的引用(置成null),这样timer线程也会终止; d)调用System.exit方法,使整个程序(所有线程)终止。

总结:Timer和TimerTask可以简单理解为Timer定时器在触发TimerTask任务调用,通常用schedule和 scheduleAtFixedRate方法来调用timertask任务,cancle来终止任务调用。

Timer简单易用,比较适合提供轻量级的计时 器功能,但是对时效性很强的任务调度请用其它方法来实现(正如javadoc所述”Timer does not offer real-time guarantees: it schedules tasks using the Object.wait(long) method”)。

ScheduledThreadPoolExecutor删除任务,该怎么解决

这时候想删除其中一个任务, 看了下API,ScheduledThreadPoolExecutor继承ThreadPoolExecutor类, 此里面有个: ------------------------------------- boolean remove(Runnable task) 从执行程序的内部队列中移除此任务(如果存在),从而如果尚未开始,则其不再运行。

------------------------------------- 我利用下面方法返回任务列表,执行其contains方法,都表示任务列表里面不包含我的任务。

------------------------------------- BlockingQueue<Runnable getQueue() 返回此执行程序使用的任务队列。

------------------------------------- ------解决的方法-------------------------------------------------------- 任务列队里的任务实际上对原始的任务做了包装,所以你删除任务的参数必须是你调用scheduleAtFixedRate返回的参数。

------解决的方法-------------------------------------------------------- API对此方法有一个说明: 此方法可用作取消方案的一部分。

它可能无法移除在放置到内部队列之前已经转换为其他形式的任务。

例如,使用 submit 输入的任务可能被转换为维护 Future 状态的形式。

运用Executors.newScheduledThreadPool的任务调度怎么解决

Timer 相信大家都已经非常熟悉 java.util.Timer 了,它是最简单的一种实现任务调度的方法,下面给出一个具体的例子: 清单 1. 使用 Timer 进行任务调度 .ibm.scheduler; import java.util.Timer; import java.util.TimerTask; public class TimerTest extends TimerTask { private String jobName = ""; public TimerTest(String jobName) { super(); this.jobName = jobName; } @Override public void run() { System.out.println("execute " + jobName); } public static void main(String[] args) { Timer timer = new Timer(); long delay1 = 1 * 1000; long period1 = 1000; // 从现在开始 1 秒钟之后,每隔 1 秒钟执行一次 job1 timer.schedule(new TimerTest("job1"), delay1, period1); long delay2 = 2 * 1000; long period2 = 2000; // 从现在开始 2 秒钟之后,每隔 2 秒钟执行一次 job2 timer.schedule(new TimerTest("job2"), delay2, period2); } } Output: execute job1 execute job1 execute job2 execute job1 execute job1 execute job2 使用 Timer 实现任务调度的核心类是 Timer 和 TimerTask。

其中 Timer 负责设定 TimerTask 的起始与间隔执行时间。

使用者只需要创建一个 TimerTask 的继承类,实现自己的 run 方法,然后将其丢给 Timer 去执行即可。

Timer 的设计核心是一个 TaskList 和一个 TaskThread。

Timer 将接收到的任务丢到自己的 TaskList 中,TaskList 按照 Task 的最初执行时间进行排序。

TimerThread 在创建 Timer 时会启动成为一个守护线程。

这个线程会轮询所有任务,找到一个最近要执行的任务,然后休眠,当到达最近要执行任务的开始时间点,TimerThread 被唤醒并执行该任务。

之后 TimerThread 更新最近一个要执行的任务,继续休眠。

Timer 的优点在于简单易用,但由于所有任务都是由同一个线程来调度,因此所有任务都是串行执行的,同一时间只能有一个任务在执行,前一个任务的延迟或异常都将会影响到之后的任务。

回页首 ScheduledExecutor 鉴于 Timer 的上述缺陷,Java 5 推出了基于线程池设计的 ScheduledExecutor。

其设计思想是,每一个被调度的任务都会由线程池中一个线程去执行,因此任务是并发执行的,相互之间不会受到干扰。

需要注意的是,只有当任务的执行时间到来时,ScheduedExecutor 才会真正启动一个线程,其余时间 ScheduledExecutor 都是在轮询任务的状态。

清单 2. 使用 ScheduledExecutor 进行任务调度 .ibm.scheduler; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; public class ScheduledExecutorTest implements Runnable { private String jobName = ""; public ScheduledExecutorTest(String jobName) { super(); this.jobName = jobName; } @Override public void run() { System.out.println("execute " + jobName); } public static void main(String[] args) { ScheduledExecutorService service = Executors.newScheduledThreadPool(10); long initialDelay1 = 1; long period1 = 1; // 从现在开始1秒钟之后,每隔1秒钟执行一次job1 service.scheduleAtFixedRate( new ScheduledExecutorTest("job1"), initialDelay1, period1, TimeUnit.SECONDS); long initialDelay2 = 1; long delay2 = 1; // 从现在开始2秒钟之后,每隔2秒钟执行一次job2 service.scheduleWithFixedDelay( new ScheduledExecutorTest("job2"), initialDelay2, delay2, TimeUnit.SECONDS); } } Output: execute job1 execute job1 execute job2 execute job1 execute job1 execute job2 清单 2 展示了 ScheduledExecutorService 中两种最常用的调度方法 ScheduleAtFixedRate 和 ScheduleWithFixedDelay。

ScheduleAtFixedRate 每次执行时间为上一次任务开始起向后推一个时间间隔,即每次执行时间为 :initialDelay, initialDelay+period, initialDelay+2*period, …;ScheduleWithFixedDelay 每次执行时间为上一次任务结束起向后推一个时间间隔,即每次执行时间为:initialDelay, initialDelay+executeTime+delay, initialDelay+2*executeTime+2*delay。

由此可见,ScheduleAtFixedRate 是基于固定时间间隔进行任务调度,ScheduleWithFixedDelay 取决于每次任务执行的时间长短,是基于不固定时间间隔进行任务调度。

回页首 用 ScheduledExecutor 和 Calendar 实现复杂任务调度 Timer 和 ScheduledExecutor 都仅能提供基于开始时间与重复间隔的任务调度,不能胜任更加复杂的调度需求。

比如,设置每星期二的 16:38:10 执行任务。

该功能使用 Timer 和 ScheduledExecutor 都不能直接实现,但我们可以借助 Calendar 间接实现该功能。

清单 3. 使用 ScheduledExcetuor 和 Calendar 进行任务调度 .ibm.scheduler; import java.util.Calendar; import java.util.Date; import java.util.TimerTask; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; public class ScheduledExceutorTest2 extends TimerTask { private String jobName = ""; public ScheduledExceutorTest2(String jobName) { super(); this.jobName = jobName; } @Override public void run() { System.out.println("Date = "+new Date()+", execute " + jobName); } /** * 计算从当前时间currentDate开始,满足条件dayOfWeek, hourOfDay, * minuteOfHour, secondOfMinite的最近时间 * @return */ public Calendar getEarliestDate(Calendar currentDate, int dayOfWeek, int hourOfDay, int minuteOfHour, int secondOfMinite) { //计算当前时间的WEEK_OF_YEAR,DAY_OF_WEEK, HOUR_OF_DAY, MINUTE,SECOND等各个字段值 int currentWeekOfYear = currentDate.get(Calendar.WEEK_OF_YEAR); int currentDayOfWeek = currentDate.get(Calendar.DAY_OF_WEEK); int currentHour = currentDate.get(Calendar.HOUR_OF_DAY); int currentMinute = currentDate.get(Calendar.MINUTE); int currentSecond = currentDate.get(Calendar.SECOND); //如果输入条件中的dayOfWeek小于当前日期的dayOfWeek,则WEEK_OF_YEAR需要推迟一周 boolean weekLater = false; if (dayOfWeek < currentDayOfWeek) { weekLater = true; } else if (dayOfWeek == currentDayOfWeek) { //当输入条件与当前日期的dayOfWeek相等时,如果输入条件中的 //hourOfDay小于当前日期的 //currentHour,则WEEK_OF_YEAR需要推迟一周 if (hourOfDay < currentHour) { weekLater = true; } else if (hourOfDay == currentHour) { //当输入条件与当前日期的dayOfWeek, hourOfDay相等时, //如果输入条件中的minuteOfHour小于当前日期的 //currentMinute,则WEEK_OF_YEAR需要推迟一周 if (minuteOfHour < currentMinute) { weekLater = true; } else if (minuteOfHour == currentSecond) { //当输入条件与当前日期的dayOfWeek, hourOfDay, //minuteOfHour相等时,如果输入条件中的 //secondOfMinite小于当前日期的currentSecond, //则WEEK_OF_YEAR需要推迟一周 if (secondOfMinite < currentSecond) { weekLater = true; } } } } if (weekLater) { //设置当前日期中的WEEK_OF_YEAR为当前周推迟一周 currentDate.set(Calendar.WEEK_OF_YEAR, currentWeekOfYear + 1); } // 设置当前日期中的DAY_OF_WEEK,HOUR_OF_DAY,MINUTE,SECOND为输入条件中的值。

currentDate.set(Calendar.DAY_OF_WEEK, dayOfWeek); currentDate.set(Calendar.HOUR_OF_DAY, hourOfDay); currentDate.set(Calendar.MINUTE, minuteOfHour); currentDate.set(Calendar.SECOND, secondOfMinite); return currentDate; } public static void main(String[] args) throws Exception { ScheduledExceutorTest2 test = new ScheduledExceutorTest2("job1"); //获取当前时间 Calendar currentDate = Calendar.getInstance(); long currentDateLong = currentDate.getTime().getTime(); System.out.println("Current Date = " + currentDate.getTime().toString()); //计算满足条件的最近一次执行时间 Calendar earliestDate = test .getEarliestDate(currentDate, 3, 16, 38, 10); long earliestDateLong = earliestDate.getTime().getTime(); System.out.println("Earliest Date = " + earliestDate.getTime().toString()); //计算从当前时间到最近一次执行时间的时间间隔 long delay = earliestDateLong - currentDateLong; //计算执行周期为一星期 long period = 7 * 24 * 60 * 60 * 1000; ScheduledExecutorService service = Executors.newScheduledThreadPool(10); //从现在开始delay毫秒之后,每隔一星期执行一次job1 service.scheduleAtFixedRate(test, delay, period, TimeUnit.MILLISECONDS); } } Output: Current Date = Wed Feb 02 17:32:01 CST 2011 Earliest Date = Tue Feb 8 16:38:10 CST 2011 Date = Tue Feb 8 16:38:10 CST 2011, execute job1 Date = Tue Feb 15 16:38:10 CST 2011, execute job1

RackNerd :美国大硬盘服务器促销/洛杉矶multacom数据中心/双路e5-2640v2/64G内存/256G SSD+160T SAS/$389/月

大硬盘服务器、存储服务器、Chia矿机。RackNerd,2019年末成立的商家,主要提供各类KVM VPS主机、独立服务器和站群服务器等。当前RackNerd正在促销旗下几款美国大硬盘服务器,位于洛杉矶multacom数据中心,亚洲优化线路,非常适合存储、数据备份等应用场景,双路e5-2640v2,64G内存,56G SSD系统盘,160T SAS数据盘,流量是每月200T,1Gbps带宽,配5...

JustHost:俄罗斯/新西伯利亚vps,512MB内存/5GB空间/不限流量/200Mbps/KVM/自由更换IP,$1.57/月

justhost怎么样?justhost是一家俄罗斯主机商,2006年成立,提供各种主机服务,vps基于kvm,有HDD和SSD硬盘两种,特色是200Mbps不限流量(之前是100Mbps,现在升级为200Mbps)。下面是HDD硬盘的KVM VPS,性价比最高,此外还有SSD硬盘的KVM VPS,价格略高。支持Paypal付款。国内建议选择新西伯利亚或者莫斯科DataLine。支持Paypal付...

日本美国站群服务器raksmart站群新增,限量低至月1.99美元

RAKsmart 商家八月份的促销活动今天更新。基本上和上个月的产品套餐活动差不多的,不过也是有简单的微调。对于RAKsmart商家还是比较了解的,他们家产品虽然这两年增加多个机房,以及在VPS主机方案上有丰富的机房和调整到一些自营机房,他们家的策划能力还是有限,基本上每个月的套餐活动都差不多。RAKsmart 在八月份看到有新增香港高防服务器可选,最高100GB防御。同时原来上个月缺货的日本独立...

scheduleatfixedrate为你推荐
iso20000认证什么是ISO20000-IT服务管理体系部署工具如何使用office2016部署软件腾讯技术腾讯简介----审计平台什么是审计工具labelforhtml标签中lable的for属性有什么作用?移动硬盘文件或目录损坏且无法读取移动硬盘文件或目录损坏且无法读取怎么办??中信银行理财宝中信银行香卡属于理财宝吗?监控插件千里眼监控软件怎么使用啊?网站推广软件破解版免费的网站推广软件,破解版web推送怎样关闭网页推送
荣耀欧洲 simcentric 美国翻墙 jsp主机 gitcafe ibox官网 双线主机 免费防火墙 免费申请网站 网通服务器托管 东莞服务器 域名dns 外贸空间 西安服务器托管 免费的asp空间 注册阿里云邮箱 rewritecond hdchina 碳云 WHMCS 更多