如何python 定时任务触发触发后台任务

后台执行的定时任务 - 简书
后台执行的定时任务
Android 中的定时任务一般有两种实现方式,一种是使用 Java API 里提供的 Timer 类,一种是使用 Android 的 Alarm 机制。这两种方式在多数情况下都能实现类似的效果。
但 Timer有一个明显的短板,它并不太适用于那些需要长期在后台运行的定时任务。我们都知道,为了能让电池更加耐用,每种手机都会有自己的休眠策略,Android 手机就会在长时间不操作的情况下自动让 CPU 进入到睡眠状态,这就有可能导致 Timer 中的定时任务无法正常运行。
而 Alarm 机制则不存在这种情况,它具有唤醒 CPU 的功能,即可以保证每次需要执行定时任务的时候 CPU 都能正常工作。
1. 创建 Alarm
主要就是借助了 AlarmManager 类来实现的。类似 NotificationManager,通过调用 Context 的 getSystemService() 方法来获取实例的,只是这里需要传入的参数是 Context.ALARM_SERVICE。
AlarmManager manager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
2. 设置定时任务
调用 AlarmManager 的 set()方法 就可以设置一个定时任务。如想设定一个 10 秒的定时任务:
long triggerAtTime = SystemClock.elapsedRealtime() + 10 * 1000;
manager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerAtTime, pendingIntent);
long triggerAtTime = System.currentTimeMillis() + 10 * 1000;
manager.set(AlarmManager.RTC_WAKEUP, triggerAtTime, pendingIntent);
set() 方法:
第一个参数:是一个整型参数,用于指定 AlarmManager 的工作类型:
ELAPSED_REALTIME:表示让定时任务的触发时间从系统开机开始算起,但不会唤醒 CPU。
ELAPSED_REALTIME_WAKEUP:表示让定时任务的触发时间从系统开机开始算起,但会唤醒 CPU。
RTC:表示让定时任务的触发时间从 1970 年 1 月 1 日 0 点开始算起,但不会唤醒 CPU。
RTC_WAKEUP:表示让定时任务的触发时间从 1970 年 1 月 1 日 0 点开始算起,但会唤醒 CPU。
使用 SystemClock.elapsedRealtime() 方法可以获取到系统开机至今所经历时间的毫秒数。
使用 System.currentTimeMillis() 方法可以获取到 1970 年 1 月 1 日 0 点至今所经历时间的毫秒数。
第二个参数:定时任务触发的时间,以毫秒为单位。
第三个参数:PendingIntent。
1. 创建一个可以长期在后台执行定时任务的服务。
public class LongRunningService extends Service {
public IBinder onBind(Intent intent) {
public int onStartCommand(Intent intent, int flags, int startId) {
new Thread(new Runnable() {
public void run() {
Log.d("LongRunningService", "executed at " + new Date().toString());
}).start();
AlarmManager manager = (AlarmManager) getSystemService(ALARM_SERVICE);
int anHour = 60 * 60 * 1000; // 这是一小时的毫秒数
long triggerAtTime = SystemClock.elapsedRealtime() + anH
Intent i = new Intent(this, AlarmReceiver.class);
PendingIntent pi = PendingIntent.getBroadcast(this, 0, i, 0);
manager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerAtTime, pi);
return super.onStartCommand(intent, flags, startId);
2. 再新建一个 AlarmReceiver 类:
public class AlarmReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
Intent i = new Intent(context, LongRunningService.class);
context.startService(i);
一旦启动 LongRunningService,就会在 onStartCommand() 方法里设定一个定时任务,这样一小时后 AlarmReceiver 的 onReceive() 方法就将得到执行,然后我们在这里再次启动 LongRunningService,这样就形成了一个永久的循环,保证 LongRunningService 可以每隔一小时就会启动一次。
3. 最后需要在打开程序的时候启动一次 LongRunningService,之后 LongRunningService 就可以一直运行了。
public class MainActivity extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = new Intent(this, LongRunningService.class);
startService(intent);
另外需要注意的是,从 Android 4.4 版本开始,Alarm 任务的触发时间将会变得不准确,有可能会延迟一段时间后任务才能得到执行。这并不是个 bug,而是系统在耗电性方面进行的优化。系统会自动检测目前有多少 Alarm 任务存在,然后将触发时间将近的几个任务放在一起执行,这就可以大幅度地减少 CPU 被唤醒的次数,从而有效延长电池的使用时间。
当然,如果你要求 Alarm 任务的执行时间必须准备无误,Android 仍然提供了解决方案。使用 AlarmManager 的 setExact() 方法来替代 set() 方法,就可以保证任务准时执行了.Pages: 1/2
主题 : 按了home键把游戏退到后台,如何让游戏仍然可以执行定时器或者action
级别: 侠客
可可豆: 426 CB
威望: 428 点
在线时间: 197(时)
发自: Web Page
来源于&&分类
按了home键把游戏退到后台,如何让游戏仍然可以执行定时器或者action&&&
做一个连连看,进游戏后开始3分钟倒计时,时间到了没连完就算输。现在的实现逻辑是一开始进游戏执行一个action,this-&runAction(CCSequence::createWithTwoActions(CCDelayTime::create(180), CCCallFunc::create(this, callfunc_selector(GameLayer::GameOver))));做完后感觉不对劲。如果玩家卡在某个地方。然后截屏,按home在进相册看游戏截图找到可以连的。然后再进游戏继续。时间并没有少。这就是一个bug了。因为游戏退到后台之后会暂停所有的action。
级别: 侠客
可可豆: 426 CB
威望: 428 点
在线时间: 197(时)
发自: Web Page
找到这篇帖子,但是他说的是nstime而不是action。另外,这样设置后游戏会通过审核吗?
级别: 版主
可可豆: 2200 CB
威望: 26364 点
在线时间: 5914(时)
发自: Web Page
用时间戳&& 戳戳戳
级别: 侠客
可可豆: 335 CB
威望: 335 点
在线时间: 500(时)
发自: Web Page
游戏进入后台,你还想时间继续,,,有没有搞错,例如你游戏玩的好好,突然有事(例如来电话)切出去,然后在进来就突然挂了,你不觉得很奇怪吗?
级别: 侠客
可可豆: 426 CB
威望: 428 点
在线时间: 197(时)
发自: Web Page
回 2楼(insul) 的帖子
何解???
级别: 侠客
可可豆: 426 CB
威望: 428 点
在线时间: 197(时)
发自: Web Page
回 3楼(xuweiping) 的帖子
那玩家就会利用这个bug,毕竟游戏过程中来电的概率很小,而玩家利用这个bug却是随时的
级别: 版主
可可豆: 2200 CB
威望: 26364 点
在线时间: 5914(时)
发自: Web Page
回 5楼(小菜菜) 的帖子
其实用时间戳也会出现你说的这个bug问题,就是玩家在游戏中修改了系统时间比较好的办法还是2楼你说的那个NSTimer
级别: 侠客
可可豆: 426 CB
威望: 428 点
在线时间: 197(时)
发自: Web Page
回 6楼(insul) 的帖子
恩,我刚才试了下int GameEngine::getTime(){&&&&time_&&&&time(&rawtime);&&&&},然后我改了系统时间,就有问题了,要是能获取一个不能改变的时间戳就好了,比如服务器的。但这样每秒都要去访问服务器,而且服务端也不会搞。而且一个单机游戏也没必要搞服务器。
级别: 侠客
可可豆: 426 CB
威望: 428 点
在线时间: 197(时)
发自: Web Page
回 6楼(insul) 的帖子
cocos2d-x 没有nstimer,我用cctimer,但是一直不进方法,不知道为什么CCTimer::timerWithTarget(this, schedule_selector(GameLayer::ChangeTime), 1);
级别: 版主
可可豆: 2200 CB
威望: 26364 点
在线时间: 5914(时)
发自: Web Page
回 8楼(小菜菜) 的帖子
这个我也不清楚了我没用cocos2dx做过实际项目
Pages: 1/2
关注本帖(如果有新回复会站内信通知您)
苹果公司现任CEO是谁?2字 正确答案:库克
发帖、回帖都会得到可观的积分奖励。
按"Ctrl+Enter"直接提交
关注CocoaChina
关注微信 每日推荐
扫一扫 浏览移动版定时任务管理设计
需要每天定时去获取四大渠道商:谷歌,百度,搜搜,搜狗的关键词,广告组,广告系列,广告商账号等汇总数据,客户可以从页面直观看到各个任务执行结果,可以手动直接去编辑更新任务的执行频率,执行参数以及启停任务;也可以新增删除任务。
设计中项目分为前后台两个项目:
后台负责定时任务的自动执行,以及提供定时任务的修改,新增,删除等服务接口,以供前台调用;前台负责展示所有任务执行状态,参数(执行频率,任务对于的渠道商id,账号id)以及任务名称(谷歌服装广告商系列报表下载),提供任务编辑功能,可以新增,删除,修改任务信息。
数据库设计:
CRON_TASK任务信息维护表:
id(自增长主键),target_object(执行对象,这里对应的是spring里配置得bean.id),cron_expression_r(执行频率,对应的quartz的执行频率),还有与业务有关的参数信息列:channel_id(渠道商id),account_id(账号id)等,创建人,创建日期...
CRON_TASK_STATUS任务状态信息表:
id(自增长主键),task_id(对应CRON_TASK.id),run_status(执行状态位,执行成功,执行失败,未执行,正在执行等),run_start_time(执行开始时间),run_end_time(执行结束时间),等..
后台代码设计:
通过数据库设计,后台已经可以直接通过数据库获取到所有任务信息了,但是如何把任务信息和我们后台的定时任务挂钩呢?
1:通过监听器或者servlet,spring等机制在web服务器自启动的时候加载所有任务信息
2:因为任务是需要支持动态新增,修改,所以这里不建议通过spring xml方式来方式来配置管理quartz任务,直接通过java代码调用得方式来管理任务;
调用quarts的基本常用步骤,以及几个常用对象:
Scheduler sched =
StdSchedulerFactory.getDefaultScheduler();
JobDetail job = new
JobDetail();
//这里很重要,我们通过jobDetail对象得setName来存储每一个任务得主键id
job.setName(e.getCronId().toString ());
//一般逻辑来说,我们需要为每一个任务建立不同得jobClass,但是我们这里只针对了一个,上面得setName就启动作用了,我们可以再CronStart里获取得任务id,那也就获取到它得bean.id了,我们就可以通过BeanFactory获取其它方式获取bean实例,这样cronStart就逻辑上变成动态的任务实例了。
job.setJobClass(CronStart.class);
CronTrigger trigger = new
CronTrigger();
String ce =
e.getCronexpression_r();
//任务执行频率
trigger.setCronexpression_r(ce);
//触发器对应的任务id主键
trigger.setName(e.getCronId().toString());
sched.scheduleJob(job,
sched.addJob(job,
3:设计cronStart
class CronStart implements Job {
&@Override&
public void
execute(JobExecutionContext executionContext)
throws&JobExecutionException&&&
//获取到任务id
executionContext.getJobDetail().getName();&&&&
//获取数据信息。。。
//调用targetObject。。
但是这里是需要执行targetObject的方法得,有两种办法
一种办法是数据库也同时存储对应得method方法名称,然后我们获取到bean实例后,通过反射到触发方法的执行
还有一种方法是我们可以让所有得任务bean去继承通过父类BasicTask,该父类提供了一个抽象方法&&&&&&&&&&&
public abstract void
doTask(CronTaskParameter ctp) throws E
也就是我们默认所有任务的执行方法就是doTask这个方法,而方法中的参数也就是数据库存储任务信息的java对象,那就可以这样来获取任务并执行了
BasicTask task =
BeanFactory.getBean("targetObject");
task.doTask(ctp);
4:为前台提供任务编辑的接口方法:
int updateCronTask(CronTaskFlow cronTaskFlow){
//截取相关代码
//更新任务链
先删除任务链&&&&&&&
sched.deleteJob(cronTaskFlow.getTaskFlowId().toString(),
sched.DEFAULT_GROUP);&
//再新增任务链
if (pause.intValue() ==
&JobDetail job = new
JobDetail();&&&&&&
&job.setJobClass(CronFlowStart.class);
job.setName(cronTaskFlow.getTaskFlowId().toString());&
&cronTrigger = new
CronTrigger();&
String ce =
cronTaskFlow.getTaskFlowexpression_r();
cronTrigger.setCronexpression_r(ce);&&&&
cronTrigger.setName(cronTaskFlow.getTaskFlowId().toString())
&sched.scheduleJob(job,
cronTrigger);&
&sched.addJob(job,
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。2017年3月 .NET技术大版内专家分月排行榜第三2017年2月 .NET技术大版内专家分月排行榜第三2016年9月 .NET技术大版内专家分月排行榜第三2016年8月 .NET技术大版内专家分月排行榜第三2016年7月 .NET技术大版内专家分月排行榜第三2016年3月 .NET技术大版内专家分月排行榜第三2016年1月 .NET技术大版内专家分月排行榜第三2015年12月 .NET技术大版内专家分月排行榜第三2015年11月 .NET技术大版内专家分月排行榜第三
2017年2月 总版技术专家分月排行榜第三
2017年5月 .NET技术大版内专家分月排行榜第一2017年4月 .NET技术大版内专家分月排行榜第一2017年3月 .NET技术大版内专家分月排行榜第一2017年2月 .NET技术大版内专家分月排行榜第一2016年10月 .NET技术大版内专家分月排行榜第一2016年8月 .NET技术大版内专家分月排行榜第一2016年7月 .NET技术大版内专家分月排行榜第一
2017年2月 总版技术专家分月排行榜第三
2017年5月 .NET技术大版内专家分月排行榜第一2017年4月 .NET技术大版内专家分月排行榜第一2017年3月 .NET技术大版内专家分月排行榜第一2017年2月 .NET技术大版内专家分月排行榜第一2016年10月 .NET技术大版内专家分月排行榜第一2016年8月 .NET技术大版内专家分月排行榜第一2016年7月 .NET技术大版内专家分月排行榜第一
2017年2月 总版技术专家分月排行榜第三
2017年5月 .NET技术大版内专家分月排行榜第一2017年4月 .NET技术大版内专家分月排行榜第一2017年3月 .NET技术大版内专家分月排行榜第一2017年2月 .NET技术大版内专家分月排行榜第一2016年10月 .NET技术大版内专家分月排行榜第一2016年8月 .NET技术大版内专家分月排行榜第一2016年7月 .NET技术大版内专家分月排行榜第一
匿名用户不能发表回复!|
每天回帖即可获得10分可用分!小技巧:
你还可以输入10000个字符
(Ctrl+Enter)
请遵守CSDN,不得违反国家法律法规。
转载文章请注明出自“CSDN(www.csdn.net)”。如是商业用途请联系原作者。后台执行的定时任务
Android中实现定时任务一般有两种机制,一种是Alarm,具有唤醒CPU的功能,
可以保证每次需要执行任务的时候CPU都能正常工作,而Timer则不能唤醒CPU。
Alarm机制的用发
创建一个LongRunningService类继承Service,重写onStartCommand方法。
public class LongRunningService extends Service {
public IBinder onBind(Intent intent) {
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
在onStartCommand方法中创建一个线程
new Thread(new Runnable() {
public void run() {
//写执行的具体逻辑,这里为了方便直接打印log
Log.i(TAG, &run: executed at &+new Date().toString());
}).start();
在onStartCommand方法中创建一个AlarmManager实例
AlarmManager manager = (AlarmManager) getSystemService(ALARM_SERVICE);
调用manager.set(int type, long triggerAtMillis, PendingIntent operation)方法。
int anHour = 60*1000;
long triggerAtTime = SystemClock.elapsedRealtime()+anH
Intent i = new Intent(this,AlarmReceiver.class);
PendingIntent pi = PendingIntent.getBroadcast(this,0,i,0);
manager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,triggerAtTime,pi);
下面简单讲一下set方法的三个参数
第一个参数是整形参数,用来指定AlarmManager的工作类型
ELAPSED_REALTIME表示让定时任务的触发时间从系统开机开始算起,但不会唤醒CPU。
ELAPSED_REALTIME_WAKEUP同上,但是会唤醒CPU。
RTC表示让定时任务的触发时间从日0点开始算起,但不会唤醒CPU。
RTC_WAKEUP同上,但是会唤醒CPU。
第二个参数用来指定定时任务触发的时间,单位为毫秒。
如果第一个参数使用ELAPSED开头的参数就传入开机至今的时间加上延迟执行的时间。
如果第一个参数使用RTC开头的参数就传入日0点至今的时间加上延迟执行的时间。
使用SystemClock.elapsedRealtime()方法可以获取到系统开机至今所经历时间的毫秒数。
使用System.currentTimeMillis()方法可以获取到日0点至今所经历时间的毫秒数。
第三个参数是PendingIntent,用于指定一个未执行的意图。
通过getBroadcast()方法获取一个能够执行广播的PendingIntent,当定时任务被触发时执行广播。
创建一个AlarmReceiver类继承BroadcastReceiver,并重写onReceive方法。
public class AlarmReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
Intent i = new Intent(context, LongRunningService.class);
context.startService(i);
当广播执行onReceive方法时,启动LongRunningService服务以完成无限循环。
在MainActivity的onCreate方法中启动服务。
Intent intent = new Intent(this, LongRunningService.class);
startService(intent);
在Manifest文件中注册BroadcastReceiver和Service
&receiver android:name=&.AlarmReceiver&&
&/receiver&
&service android:name=&.LongRunningService&/&
阅读(...) 评论()

我要回帖

更多关于 java 触发定时任务 的文章

 

随机推荐