任务调度

一个任务调度

最近把以前项目中用的任务调度提了出来,做了一个Demo。

任务调度用到的组件是quartz.net。关于quartz.net的文章网上有很多了,这里再简单介绍下。

首先是创建一个作业明细

 

然后是创建一个触发器

 

最后把创建的两样组合起来就新增了一个作业了

 

作业必须实现IJob接口

这里用了一个基类来实现IJob接口,基类里有一个抽象方法,其他作业子类只要继承这个基类并实现这个抽象方法就行了。

public void Execute(IJobExecutionContext context)
        {
            //Quartz.Collection.ISet<JobKey> jobKeys = context.Scheduler.GetJobKeys(
            //      Quartz.Impl.Matchers.GroupMatcher<JobKey>.GroupEquals(JobHelp.jobGroupName));    //取所有运行的作业

            var task = context.MergedJobDataMap["task"] as ScheduleTask;
            string message = string.Format("{0}的『Execute』从『IJobExecutionContext』读取不到作业计划!", ""); // this.FullDevName
            if (task == null) throw new Exception(message);

            //刷新作业计划信息,防止作业计划配置发生改变
            string sql = "select * from ScheduleTask where [email protected]";
            var taskNew = _scheduleTask.GetFirst<ScheduleTask>(sql, new { id = task.Id });

            if (taskNew == null)
            {
                //计划已经被删除,则删除此作业
                context.Scheduler.DeleteJob(context.JobDetail.Key);
                Log.Logger.InfoFormat(string.Format("{0}作业计划为空,该记录可能已经被删除。", taskNew.MethodName));
                return; //退出
            }

            //作业不允许使用
            if (!taskNew.Allowused)
            {
                //不从调度计划中删除本作业,因为有可能又启用该作业计划
                Log.Logger.InfoFormat(string.Format("{0}作业计划不允许使用,跳过此次执行。", taskNew.MethodName));
                return; //退出
            }
            if (taskNew != task)
            {

                //脏数据,删除此作业,然后重新创建一个
                Log.Logger.InfoFormat("{0}的作业计划属性已更改,将删除该计划的实现作业,然后重新创建一个作业,并尝试调度它...", taskNew.MethodName);
                //作业计划属性发生变更,重新启动作业
                Tuple<IJobDetail, ITrigger> tuple = JobHelp.RestartJob(context.Scheduler, task, taskNew);
                Log.Logger.InfoFormat("{0}重新创建并调度作业完成,『IJOB.Execute』退出。作业计划:{1},作业:{2},触发器:{3},表达式:{4}。", taskNew.MethodName, taskNew.MethodName, tuple.Item1.Key.Name, tuple.Item2.Key.Name, taskNew.CronExpression);
                return; //退出
            }

            //执行具体作业的业务逻辑
            ExecuteJobImpl(context);

            //更新执行时间
            taskNew.LastTime=DateTime.Now.ToString();
            taskNew.NextTime = string.Format("{0:G}", context.NextFireTimeUtc.Value.AddHours(8));
            UpdateTime(taskNew);
        }

新增作业

怎样新增一个作业呢?

新增一个作业也很简单,只需在TaskManageDemo.Task项目下添加一个类,并继承作业父类实现抽象方法就可以了。

那怎样来配置呢?

实现了作业后,点击新增按钮来增加一个作业。

新增的作业是怎样被触发的呢?

这里我用了一个系统作业来唤醒新增的作业和删除不需要的作业。

protected override void ExecuteJobImpl(Quartz.IJobExecutionContext context)
        {
            //取所有运行的作业
            Quartz.Collection.ISet<JobKey> jobKeys = context.Scheduler.GetJobKeys(
                   Quartz.Impl.Matchers.GroupMatcher<JobKey>.GroupEquals(JobHelp.jobGroupName));

            string sql = "select * from ScheduleTask where [email protected]";
            var taskRuning = new List<ScheduleTask>();//正在运行的作业
            var taskInDb = _scheduleTask.Query<ScheduleTask>(sql, new { ClassName = "SysJob" }); //存在于数据库的作业,不包括系统作业
            foreach (var jk in jobKeys)
            {
                IJobDetail job = context.Scheduler.GetJobDetail(jk);
                ScheduleTask task = job.JobDataMap["task"] as ScheduleTask;
                if (task == null || task.ClassName == "SysJob") continue;  //不检查系统作业  

                //在数据库检测一次
                var taskInDb2 = taskInDb.ToList().FirstOrDefault(a => a.Id == task.Id);
                if (taskInDb2 == null)
                {
                    context.Scheduler.DeleteJob(jk); //删除该作业
                    Log.Logger.InfoFormat("作业计划『{0}』已经不存在于数据库。", task.ClassName);
                    continue;
                }
                taskRuning.Add(taskInDb2);

                if (taskInDb2 != task)
                {

                    //脏数据,删除此作业,然后重新创建一个
                    Log.Logger.InfoFormat("{0}的作业计划属性已更改,将删除该计划的实现作业,然后重新创建一个作业,并尝试调度它...", taskInDb2.ClassName);
                    //作业计划属性发生变更,重新启动作业
                    Tuple<IJobDetail, ITrigger> tuple = JobHelp.RestartJob(context.Scheduler, task, taskInDb2);
                    Log.Logger.InfoFormat("{0}重新创建并调度作业完成,『IJOB.Execute』退出。作业计划:{1},作业:{2},触发器:{3},表达式:{4}。", taskInDb2.ClassName, taskInDb2.ClassName, tuple.Item1.Key.Name, tuple.Item2.Key.Name, taskInDb2.CronExpression);
                    return; //退出
                }
            }
            //过滤出新增的作业
            var newTask = taskInDb.Except(taskRuning);
            if (newTask.Count() > 0)
            {
                //动态增加作业
                Log.Logger.InfoFormat("系统作业检测到有{0}个新增作业计划,开始创建这些作业...", newTask.Count());
                foreach (var task in newTask)
                    TaskManageDemo.Utility.Common.Execute(ScheduleJobByPlan, context.Scheduler, task, "创建作业失败,作业计划名称:{0}", task.ClassName); 

                Log.Logger.InfoFormat("系统作业创建作业完毕,共创建{0}个作业。", context.Scheduler.GetJobKeys(Quartz.Impl.Matchers.GroupMatcher<JobKey>.GroupEquals(JobHelp.jobGroupName)).Count - 1);
            }
            //系统作业执行完毕
            Log.Logger.InfoFormat("系统轮询作业执行完毕,目前共{0}个作业正在运行。", context.Scheduler.GetJobKeys(Quartz.Impl.Matchers.GroupMatcher<JobKey>.GroupEquals(JobHelp.jobGroupName)).Count);
            context.Put("ExecResult", "系统作业执行完成。");

            //Log.Logger.ErrorFormat("本次运行时间{0},下次运行时间{1}", DateTime.Now.ToString(), context.NextFireTimeUtc.Value.DateTime.AddHours(8).ToString());
        }

主要的应该也就这些,当然这是个Demo,有很多地方不是很完善。

源码下载

https://git.oschina.net/bin88123/TaskManageDemo

时间: 2024-08-03 01:46:10

任务调度的相关文章

开源分布式任务调度平台Cuckoo-Schedule

1         概述 1.1      平台概述 Cuckoo-Schedule是基于Quartz-Schedule的轻量级任务调度框架,具有易学习.易上手.开发高效稳定的特点.Demo地址:http://cuckoo.hellosr.com,测试用户:guest,密码:123456. Cuckoo-Schedule对调度模块与执行模块进行解耦,调度模块支持集部署.任务分组.任务依赖.权限管理.邮件告警.调度日志记录等功能,并提供WEB页面对任务进行管理,支持任务实时调度情况的查看.变更以及

任务调度框架-Quartz.Net

使用Quartz.Net依赖于以下3个组件:Common.Logging.dll.Common.Logging.Core.dll.Quartz.dll 简单封装 1 using Quartz; 2 using Quartz.Impl; 3 using System; 4 using System.Collections.Generic; 5 using System.Linq; 6 using System.Text; 7 using System.Threading.Tasks; 8 9 na

java计划任务调度框架quartz结合spring实现调度的配置实例代码分享

点击链接加入群[JavaEE(SSH+IntelliJIDE+Maven)]:http://jq.qq.com/?_wv=1027&k=L2rbHv 一:quartz简介 OpenSymphony 的Quartz提供了一个比较完美的任务调度解决方案. Quartz 是个开源的作业调度框架,定时调度器,为在 Java 应用程序中进行作业调度提供了简单却强大的机制. Quartz中有两个基本概念:作业和触发器.作业是能够调度的可执行任务,触发器提供了对作业的调度 二:quartz spring配置详

java sql编辑器 动态报表 数据库备份还原 quartz定时任务调度 自定义表单 java图片爬虫

获取[下载地址]   QQ: 313596790   [免费支持更新] 三大数据库 mysql  oracle  sqlsever   更专业.更强悍.适合不同用户群体 [新录针对本系统的视频教程,手把手教开发一个模块,快速掌握本系统] A 集成代码生成器(开发利器)+快速构建表单;            QQ:313596790 freemaker模版技术 ,0个代码不用写,生成完整的一个模块,带页面.建表sql脚本,处理类,service等完整模块 B 集成阿里巴巴数据库连接池druid;

Linux crontab任务调度

一.crontab说明 Linux crontab任务调度是在规定的时间频率内去执行相应的任务. 二.crontab文件详情 1.crontab文件在Linux中的/etc/crontab 2.查看crontab文件  # vi /etc/crontab  文件描述如下 SHELL=/bin/bashPATH=/sbin:/bin:/usr/sbin:/usr/binMAILTO=rootHOME=/ # For details see man 4 crontabs # Example of j

任务调度器quartz的使用

1.quartz的获取. 可參照:Quartz任务调度模型实例 2.开发思路: 要使用定时器quartz.先弄清楚三个概念:调度器.任务.触发器.开发也是依照这三个方面来开发, 1>写一个Job的实现类.里面是你自己要完毕的业务逻辑: 2>写Trigger的实现类,主要有SimpleTrigger和CronTrigger这两个子类.来决定调度方案: 当仅需触发一次或者以固定时间间隔周期运行,SimpleTrigger是最适合的选择: 而CronTrigger则能够通过Cron表达式定义出各种复

《CLR via C#》之线程处理——任务调度器

<CLR via C#>之线程基础--任务调度器 <CLR via C#>之线程基础--任务调度器线程池任务调度器设置线程池限制如何管理工作者线程同步上下文任务调度器自定义TaskScheduler派生类 FCL提供了两个派生子TaskScheduler的类型:线程池任务调度器(thread pool task scheduler),和同步上下文任务调度器(synchronization context task scheduler).默认情况下都使用线程池任务调度器. 线程池任务

quartz任务调度学习一

1.实现定时任务的几种方式: crontab 命令 + sql语句 python脚本 + sql语句 spring + JDK Timer spring + Quartz 2.Quartz概述: Quartz是java领域中最著名的定时任务调度工具,具有以下特性: 强大的调度功能 灵活的应用方式 负载均衡 高可用特性 易于spring集成 3.基础概念: Quartz 任务调度的核心元素是 scheduler, trigger 和 job,其中 trigger 和 job 是任务调度的元数据,

采用Windows服务任务调度Quartz.NET

Windows服务使用标准的Csharp编写,任务调度框架采用开源的Quartz.NET.    首先创建Windows服务-JobService     其次创建类库项目-JobLibrary    整体解决方案架构图如下:     在JobLibary中添加Quartz.NET的Nuget包引用,添加之后,vs会自动添加一系列的依赖项,这些依赖项是必须的,别手抖删掉了.            其次再添加Common.Logging.Log4Net1211的Nuget包,他是Log4net的另

linux基础操作----任务调度指令

在很多的时候,我们需要在指定的时间,做些事情,比如:在凌晨2:00-3:00之间做个系统备份.此时,我们就需要使用到了任务调度指令. 规定系统在指定的事件完成指定的任务过程就是"任务调度指令" 设置使用: > crontab–e       //编辑任务调度指令 > crontab–l       //查看任务调度指令 版权声明:本文为博主原创文章,未经博主允许不得转载.