java 定时器cancel之后要重启怎么解决
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java 定时器cancel之后要重启怎么解决相关的知识,希望对你有一定的参考价值。
参考技术A 你不要执行cancel 可以暂停定时器的 或者用Spring 的 quartz 定时器来执行调度任务。追问你不要执行cancel 可以暂停定时器的 ? 这句话什么意思?quartz
我以前用过
你可以 用线程去暂停/延迟这个定时器
追问我直接cancle后再重新new了,但是不知道这样会不会有什么别的影响。
参考技术B 你说的是timer?不能重启。只能用一次。追问嗯,那我在cancel之后,只能在重新new一个?
参考技术C ---------任务类,需要继承Taskpublic class MyTask extends TimerTask
@Override
public void run()
System.out.println("正在做任务");
--------示例类
public class MyDemo
private Timer timer = new Timer();
private MyTask myTask = new MyTask();
public void doTask(int i)
if (i == 1)
System.out.println("开始任务");
if (timer == null)
timer = new Timer();//新Timer
myTask = new MyTask();//新Task
timer.schedule(myTask, 3000, 1000);
if (i == 0)
System.out.println("取消任务");
timer.cancel();
timer=null;//置空方便内存回收
myTask=null;//置空方便内存回收
public static void main(String[] args) throws Exception
MyDemo myDemo = new MyDemo();
Scanner scanner = new Scanner(System.in);//输入1执行,0停止
while (true)
int param = scanner.nextInt();
System.out.println("输入:" + param);
myDemo.doTask(param);
-----------
注:
1、网上找了好多方法,很多人说在timer.cancel()之后再new Timer()就好了,我试过还是不行。
2、其实还得再new Task(),让新的Timer服务于新的Task;
3、之前的Timer在cancel()之后不会再重启了,该方法不是暂停的原任务后继续执行原任务,
而是停止了原任务后去执行一个新任务。
缺点:容易出现线程问题,定时任务建议使用ScheduledExecutorService中的方法,或是使用@scheduled注解方式
以代码的方式管理quartz定时任务的暂停重启删除添加等
【前言】在项目的管理功能中,对定时任务的管理有时会很常见。因为我们不能指望只在配置文件中配置好定时任务就行了,因为如果要控制定时任务的 “暂停” 呢?暂停之后又要在某个时间点 “重启” 该定时任务呢?或者说直接 “删除” 该定时任务呢?要改变某定时任务的触发时间呢? “添加” 一个定时任务对于系统的使用者而言,是不太现实的,因为一个定时任务的处理逻辑他是不可能完成的,还是必须得由开发人员去添加。一般来说,是针对 “已有” 定时任务进行的一些操作,这时候就必须要用到代码来操作了,因为此时通过配置来管控是不太现实的。
版本:Spring4.x + quartz2.x
首先,开发人员会在配置文件中配置一个定时任务(定时任务的实现略……)
- <bean id="job1" class="org.test.job.TestJob2" />
- <!-- 定义触发器来管理任务bean -->
- <bean id="cronTriggerJob1"
- class="org.springframework.scheduling.quartz.CronTriggerFactoryBean"
- p:cronExpression="0 52 17 * * ? *" >
- <property name="jobDetail">
- <bean class="org.springframework.scheduling.quartz.JobDetailFactoryBean"
- p:durability="true"
- p:jobClass="org.test.job.TestJob1"
- />
- </property>
- </bean>
- </bean>
- <!-- 执行实际的调度 -->
- <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
- <property name="triggers">
- <list>
- <ref bean="cronTriggerJob1" />
- </list>
- </property>
- </bean>
我们怎么根据配置的bean来操作该定时任务的管理呢?
需查阅spring4.x结合quartz2.x的底层API,并搞清楚以下概念:
1)Trigger trigger. trigger.getKey()会得到两个东西——group:DEFAULT(默认的group name)、name(triggerName)。其中name对应的就是配置文件中配置的trigger的bean的id(或name)
2)trigger.getJobKey()一样会得到两个东西——group:DEFAULT(默认的group name)、name(jobName)。其中jobName对应的就是配置文件中job的bean的id或name(本例为job1)
注:以上粗体字的部分即为代码管理定时任务的关键之处!
3)如何根据jobName查找到他关联到的trigger呢?
quartz1.x还有这种语法,不过quartz2.x已经废除了:
quartz1.x Trigger trigger = sched.getTrigger(jobName,TRIGGER_GROUP_NAME);
quartz2.x的相关语法(Scheduler类的方法)更为丰富,如下:
public abstract List<? extends Trigger> getTriggersOfJob(JobKey paramJobKey)
throws SchedulerException;
public abstract List<String> getTriggerGroupNames()
throws SchedulerException;
public abstract Set<TriggerKey> getTriggerKeys(GroupMatcher<TriggerKey> paramGroupMatcher)
throws SchedulerException;
public abstract Trigger getTrigger(TriggerKey paramTriggerKey)
throws SchedulerException;
为了改变触发时间,
Trigger trigger = TriggerBuilder.forJob(String jobName).newTrigger()..withSchedule(CronScheduleBuilder.cronSchedule(time))build();
然后再用Scheduler调度类去执行:
schedler.resumeTrigger(trigger.getKey());
根据trigger得到相应的JobDetail:
JobDetail jobDetail = (JobDetail) trigger.getJobDataMap().get("jobDetail");
下面是对定时任务的管理(暂停、重启、删除):
- //暂停
- //schduler.pauseTrigger(TriggerKey triggerKey)
- scheduler.pauseJob(JobKey.jobKey("job1"));//停止触发器
- Thread.sleep(1000*60*2);
- //恢复
- //scheduler.resumeJob(JobKey jobKey)则可恢复一个具体的job,
- scheduler.resumeTrigger(TriggerKey.triggerKey("cronTriggerJob1"));
- Thread.sleep(1000*60*2);
- //删除
- //没有deleteTrigger的方法
- scheduler.deleteJob(JobKey.jobKey("job1"));
- Thread.sleep(1000*60*2);
- //删除后再次尝试重启(会失效)
- scheduler.resumeTrigger(TriggerKey.triggerKey("cronTriggerJob1"));
代码经测试,有效,并注意到:
当resume一个定时任务时,会立即执行该定时任务,执行完此次,然后再按原先设定的时间来定期执行;
当删除一个任务后,就算再次resume时,会失效,即并不会被恢复了。
=========================================
Spring bean必须注意的几点:
1)bean的id和name是一回事儿;
2)当一个bean类继承了InitializingBean接口后,必须实现其setBeanName(String name)抽象方法。name一般是bean的id或name属性值,此时bean实例化时方法的顺序为setProperties(String propName)->setBeanName()->afterPropertiesSet();
3)当为了获得一个bean对外提供的接口方法时,必须先获得这个bean的bean对象,通过Spring的SpringContextHolder.getBean(beanId) (其中beanId为bean的id或name属性值)。而不能通过new或者getInstance(获取单例)的方式,否则获取不到该bean的其他属性值!
以上是关于java 定时器cancel之后要重启怎么解决的主要内容,如果未能解决你的问题,请参考以下文章
java/安卓关于Timer,task,schedule重新设置定时任务时间的问题