zoukankan      html  css  js  c++  java
  • 任务调度中心 (普通版)【原】

    任务调度中心

    主要依赖quartz.jar相关类 判断cron表达式 , 在下次即将执行的时间在指定时间内时, 从线程池中取线程进行调度 (普通版)

    相关类

    1. MyTrigger.java (主入口)
    2. MyJob.java
    3. MyCallable.java

    详细说明已都在java代码中体现.

    相关jar包

    quartz-2.2.3.zip

    MyTrigger.java (主函数入口)

    package com.testdemo.pcis.isc.job.king;
    
    import java.text.SimpleDateFormat;
    import java.util.UUID;
    import java.util.concurrent.Callable;
    import java.util.concurrent.Executors;
    import java.util.concurrent.Future;
    import java.util.concurrent.ScheduledExecutorService;
    import java.util.concurrent.TimeUnit;
    
    import org.quartz.CronScheduleBuilder;
    import org.quartz.JobBuilder;
    import org.quartz.JobDetail;
    import org.quartz.Scheduler;
    import org.quartz.Trigger;
    import org.quartz.TriggerBuilder;
    import org.quartz.impl.StdSchedulerFactory;
    /**
     * 触发器小例子.
     * 1. 模拟从数据库中取完整信息,得到cron表达式
     * 2. 判断时间是否在inSeconds(10)秒以内需要执行该任务
     * 3. 如果在inSeconds(10)秒以内,从线程池中启动新线程,发送数据
     * @author King
     * @time 2016/07/07
     */
    public class MyTrigger {
        //指定任务处于inSeconds秒内时,就开启新线程任务
        private static final int inSeconds = 10;////时间格式化器
        private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
        //线程池
        private static final ScheduledExecutorService executor = Executors.newScheduledThreadPool(2);  
        
        public static void main(String[] args) throws Exception {
            // 模拟从数据库中取到一个与计划相关完整单行信息
            Object dataFromDb = new Object();
            
            // 模拟dataFromDb该行信息中cron表达式如下
            String cronArg = "50 45 14 * * ?";
            
            // 得到计划scheduler
            Scheduler scheduler = new StdSchedulerFactory().getScheduler();
    
            // 创建工作任务job
            JobDetail job = JobBuilder.newJob().ofType(MyJob.class)
                    .withIdentity("job1", "group1").build();
    
            // 创建触发器trigger
            // 如果cronArg表达式不正确,会报java.text.ParseException,可以用来判断前台页面插入的cron表达式是否合法
            Trigger trigger = TriggerBuilder.newTrigger()
                    .withIdentity("trigger1", "group1").startNow()
                    // .withSchedule(SimpleScheduleBuilder.repeatSecondlyForTotalCount(10,2))
                    .withSchedule(CronScheduleBuilder.cronSchedule(cronArg))
                    // .withSchedule(CalendarIntervalScheduleBuilder.calendarIntervalSchedule().withIntervalInHours(2))
                    .build();
            
            // 对该计划指定运行 的工作任务和触发器,该行一定要有,不然触发器的下次执行时间会为null
            scheduler.scheduleJob(job, trigger);
    
            // 开始计划的执行,但这里最终目的只需要得到下次执行时间,而不需要真正执行,不然会启动线程增加性能消耗
             //s.start();
    
            //判断触发器trigger的下次执行时间是否临近
            boolean flag = nearToRun(trigger);
            
            //如果临近,那么开启新线程
            if(flag){
                startNewThread(trigger,dataFromDb);
            }
                
            
            
            // 关闭计划scheduler
    //        s.shutdown(true);
        }
        
        /**
         * 判断触发器trigger的下次执行时间是否临近inSeconds秒以内(目前为10秒以内)
         * @param trigger
         * @return
         */
        public static boolean nearToRun(Trigger trigger){
            // 打印下次执行时间,得到结果
            System.out.println("trigger下次触发时间:" + sdf.format(trigger.getNextFireTime()));
            // 获取时差 = 该任务下次执行时间 - 当前时间
            long delayTimeMillis =  trigger.getNextFireTime().getTime() - System.currentTimeMillis();
            // 如果 0秒<时差<10秒 ,那么启动线程(这个10秒到时由properties.参数决定)
            if (delayTimeMillis > 0 && delayTimeMillis < inSeconds * 1000) {
                return true;
            }else{
                return false;
            }
        }
        
        
        /**
         * 从线程池开启新线程
         * @param trigger 触发器
         * @param dataFromDb 从数据库中取到的单行完整信息
         * @throws Exception
         */
        public static void startNewThread(Trigger trigger,Object dataFromDb) throws Exception{
            //模拟从数据库中取到的数据dataInDb
            UUID uuid = UUID.randomUUID();
            Callable<String> call = new MyCallableImpl(uuid.toString(),dataFromDb);
            // 再次获取时差,因为离executor.schedule(arg...)越近,越精确
            long delayTimeMillis2 =  trigger.getNextFireTime().getTime() - System.currentTimeMillis();
            Future future = executor.schedule(call, delayTimeMillis2,TimeUnit.MILLISECONDS);
            //如果1 * 3600 * 1000 = 1小时内还得不到返回信息就会报java.util.concurrent.TimeoutException,该参数从dataFromDb中提取
            String result = (String) future.get( 1 * 3600 * 1000,TimeUnit.MILLISECONDS);
            System.out.println("刚才启动的线程结束了,返回信息为:" + result);
        }
    
    }

    MyJob.java

    为了触发器而创建的类,实际情况并不会运行,但仍旧依赖该job,只要有一个空实现即可.

    package com.testdemo.pcis.isc.job.king;
    
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    import org.quartz.Job;
    import org.quartz.JobExecutionContext;
    import org.quartz.JobExecutionException;
    
    /**
     * Job实现类
     * @author King
     * @time 2016/07/07
     */
    public class MyJob implements Job { 
    
        @Override 
        public void execute(JobExecutionContext arg0) throws JobExecutionException { 
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS"); 
            System.out.println(sdf.format(new Date())+"I'm runing");
            try {
                Thread.currentThread().sleep(1*1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(sdf.format(new Date())+"I'm runing"); 
        } 
     
    } 

    MyCallable

    相当于线程的Runnable,实现类似于run()的call()方法,对真实业务进行调用

    package com.testdemo.pcis.isc.job.king;
    
    import java.util.concurrent.Callable;
    
    /**
     * Callable实现类
     * @author King
     * @time 2016/07/07
     */
    class MyCallable implements Callable<String> {
        private Object dataFromDb;
        public String name;
    
        public MyCallable() {
            super();
        }
    
        public MyCallable(String name, Object dataFromDb) {
            this.name = name;
            this.dataFromDb = dataFromDb;
        }
    
        @Override
        public String call() throws Exception {
            System.out.println("CallableImpl:" + name + " is start");
            // 把dataFromDb数据发送给指定URL,dataFromDb本身包含了URL地址,及超时时间等重要信息
            // send(dataFromDb)/自定义一个方法用于发送
            // 模拟发送情况,睡一会
            Thread.sleep(3 * 1000);
            System.out.println("CallableImpl:" + name + "is end");
            // 返回相关信息
            return "success";
        }
        
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public Object getDataFromDb() {
            return dataFromDb;
        }
    
        public void setDataFromDb(Object dataFromDb) {
            this.dataFromDb = dataFromDb;
        }
    }

    其它无关tips

    得到一些job和trigger的状态

            JobDetail jobDetail = scheduler.getJobDetail(new JobKey("job1","group1"));
            System.out.println("jobDetail:	"+jobDetail);
    
            TriggerState  triggerState = scheduler.getTriggerState(new TriggerKey("trigger1","group1"));
            System.out.println("triggerState:	"+triggerState);
    View Code
  • 相关阅读:
    UVa 116 单向TSP(多段图最短路)
    POJ 1328 Radar Installation(贪心)
    POJ 1260 Pearls
    POJ 1836 Alignment
    POJ 3267 The Cow Lexicon
    UVa 1620 懒惰的苏珊(逆序数)
    POJ 1018 Communication System(DP)
    UVa 1347 旅行
    UVa 437 巴比伦塔
    UVa 1025 城市里的间谍
  • 原文地址:https://www.cnblogs.com/whatlonelytear/p/5650058.html
Copyright © 2011-2022 走看看