java 任务调度实现的总结

Timer

Timer的核心是Timer和TimerTask,Timer负责设定TimerTask的起始与间隔执行时间,使用者需要建立一个timeTask的继承类,实现run方法,然后将其交给Timer使用即可。

Timer的设计是一个TaskList和一个TaskThread。Timer将接到的任务交给TaskList中,TaskList按照最初执行时间进行排序。TimerThread在创建Timer会成为一个守护线程。这个线程会轮询任务,找到一个最近要执行的任务,然后休眠,当到达最近要执行任务的开始时间点,TimerThread被唤醒并执行任务。之后Timer更新最近要执行的任务,继续休眠。

缺点:所有任务都是串行的,前一个任务的延迟或异常会影响到后面的任务。

demo:

1 Timer timer = new Timer();
2 TimeTask task = new TimeTask(){
3         public void run(){
4          //具体业务        
5     }
6 };
7 timer.scheduleAtFixedRate(task, new Date(), 1* 30 * 1000l);

ScheduledExecutor

java 5退出了ScheduledExecutor框架, 与timer不同的是,任务执行时是并发的,相互之间不受干扰,(保留意见,不一定非得是并发执行的就好),只有当任务执行时间到的时候,scheduedExecutor才会真正的执行线程,其余时间ScheduledExecutor都在轮询任务的状态。

 1 public class ScleduledExecutorTest implements Runnable{
 2   private String jobName = "";
 3   public ScheduledExecutorTest(String jobName){
 4   super();
 5    this.jobName = jobName;    
 6   }  
 7    public void run(){
 8      System.out.println("execute " + jobName);
 9    }   
10    public static void main(String[] args){
11    ScheduledExecutorService service = Executors.newScheduledThreadPool(10);
12    service.scheduleAtFixRate(new ScheduledExecutorTest("job1"),1,1,TimeUnit.SECONDS); 
13 service.scheduleWithFixedDelay(
14                 new ScheduledExecutorTest("job2"), 1,
15                 1, TimeUnit.SECONDS);
16    }
17 }

注意,能做定时执行的只能是newScheduledThreadPool 这个是专门做调度任务的,其他的线程池特性如下:

newSingleThreadExecutor:创建一个单线程的线程池。这个线程池只有一个线程在工作,也就是相当于单线程串行执行所有任务。如果这个唯一的线程因为异常结束,那么会有一个新的线程来替代它。此线程池保证所有任务的执行顺序按照任务的提交顺序执行。

newFixedThreadPool:创建固定大小的线程池。每次提交一个任务就创建一个线程,直到线程达到线程池的最大大小。线程池的大小一旦达到最大值就会保持不变,如果某个线程因为执行异常而结束,那么线程池会补充一个新线程。

newCachedThreadPool:创建一个可缓存的线程池。如果线程池的大小超过了处理任务所需要的线程,那么就会回收部分空闲(60秒不执行任务)的线程,当任务数增加时,此线程池又可以智能的添加新线程来处理任务。此线程池不会对线程池大小做限制,线程池大小完全依赖于操作系统(或者说JVM)能够创建的最大线程大小。

newScheduledThreadPool:创建一个大小无限的线程池。此线程池支持定时以及周期性执行任务的需求。

newSingleThreadExecutor:创建一个单线程的线程池。此线程池支持定时以及周期性执行任务的需求。

 

并且线程池在停止的时候所用的shutdown与shutdownNow是不一样的,shutdown会继续执行并且完成所有未执行的任务,shutdownNow 会清楚所有未执行的任务并且在运行线程上调用interrupt() 。然而interrupt仅仅是在当前线程中打一个停止的标记。还需要加一个判断才能对线程的停止。

Thread.java提供了两个方法:

this.interrupted();

this.isInterrupted();

官方帮助文档对interrupted方法的解释是:

调用后,线程的中断状态被清除,也就是如果线程中断了,第一次返回true,第二次返回false。 并且这是一个静态方法。

isInterrupted不是一个静态方法,也不会清除中断状态。

中断线程通过标记判断,要么抛出异常,要么直接return。

 

ScheduledExecutor可以与Calendar实现更复杂的调度,比如制定每周的某个时间段执行。

也就是在执行线程中加上了Calandar的判断

Calendar ca = Calendar.getInstance();
        int h = ca.get(Calendar.HOUR_OF_DAY);
        int mi = h*60+ca.get(Calendar.MINUTE);
        int ss = ca.get(Calendar.SECOND);

通过if进行判断,要注意,调度器的唤醒时间最好是各个线程激活的最大公约数。

 

Quartz

 

需要更精准的调度,需要使用Quartz框架了。

public static void main(String args[]){
   UpdateJob.task(AutoJob.class,"0/1 * * * * ?" );
}
public class UpdateClientTimer {

    public static void task(Class cls, String expression) throws SchedulerException {

        SchedulerFactory schedulerFactory = new StdSchedulerFactory();
        Scheduler scheduler = schedulerFactory.getScheduler();
        long ctime = System.currentTimeMillis();
        JobDetail jobDetail = new JobDetail("detail", "group", cls);
        CronTrigger cronTrigger = new CronTrigger("cronTrigger", "group");
        try {
            CronExpression cexp = new CronExpression(expression);
            cronTrigger.setCronExpression(cexp);
        } catch (Exception e) {
            e.printStackTrace();
        }
        scheduler.scheduleJob(jobDetail, cronTrigger);
        scheduler.start();
    }
}
调度周期是 "0/1 * * * * ?" 更精准的调度需要自行配置。
UpdateClientTimer 大体与官方文档相当。真正执行业务在本例的Autojob中。
public class AutoJob implements Job {
    public void execute(JobExecutionContext arg0) throws JobExecutionException {
        Calendar ca = Calendar.getInstance();
        int h = ca.get(Calendar.HOUR_OF_DAY);
        int mi = h*60+ca.get(Calendar.MINUTE);
        int ss = ca.get(Calendar.SECOND);
        
        if(过滤条件){
    
        }

}

Quartz的核心类包括Scheduler,job以及Trigger。其中job负责定义需要执行的任务,trigger负责设置调度策略,Scheduler 将二者组装在一起。

有相关的官方说明文档,可以直接拿demo用。

 

 

 

 



 

转载于:https://www.cnblogs.com/caobojia/p/6344628.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值