java实现定时任务

Wesley13
• 阅读 427

普通thread--

这是最常见的, 创建一个thread,然后让它在while循环里一直运行着,

 通过sleep方法来达到定时任务的效果。这样可以快速简单的实现,

package com.iotek.classtype;

public class Task1 {
   public static void main(String[] args) {
    final long timeInterval=1000;
    Runnable runnable =new Runnable() {
        
        @Override
        public void run() {
            while(true) {
                 System.out.println("hello !!!");
                 
                 try {
                    Thread.sleep(timeInterval);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    };
    Thread thread=new Thread(runnable);
    thread.start();
}
}

Timer类

Timer类可以调度任务,TimerTask则是通过在run()方法里实现具体任务。 Timer实例可以调度多任务,它是线程安全的。

当Timer的构造器被调用时,它创建了一个线程,这个线程可以用来调度任务。 下面是代码:

通过

timer.schedule()方法

package com.iotek.classtype;

import java.util.Timer;
import java.util.TimerTask;

public class Task2 {
  public static void main(String[] args) {
    
      TimerTask  timerTask=new TimerTask() {
        
        @Override
        public void run() {
            System.out.println("HELLO");
            
        }
    };
    
    Timer timer=new Timer();
    long delay=0;
    long intevalPeriod=1*1000;
    timer.schedule(timerTask, delay, intevalPeriod);
}
}

ScheduledExecutorService

ScheduledExecutorService是从Java SE5的java.util.concurrent里,做为并发工具类被引进的,这是最理想的定时任务实现方式。

相比于上两个方法,它有以下好处:

相比于Timer的单线程,它是通过线程池的方式来执行任务的

可以很灵活的去设定第一次执行任务delay时间

提供了良好的约定,以便设定执行的时间间隔

package com.iotek.classtype;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class Task3 {
 public static void main(String[] args) {
    
     Runnable runnable=new Runnable() {
        
        @Override
        public void run() {
        System.out.println("hello");
        }
    };
    ScheduledExecutorService service=Executors.newSingleThreadScheduledExecutor();
    service.scheduleAtFixedRate(runnable, 10,1,TimeUnit.SECONDS);
}
}

JAVA实现定时任务的几种方式

  • JDK 自带的定时器实现

Timer类 
这个类允许你调度一个java.util.TimerTask任务。主要有以下几个方法:

java实现定时任务 java实现定时任务

//schedule(TimerTask task, long delay) 延迟 delay 毫秒 执行
   public static void main(String[] args) {
    for(int i=0;i<10;i++) {
        new Timer().schedule(new TimerTask() {
            
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName()+" run");
                
            }
        }, 1000);
    }

View Code

java实现定时任务 java实现定时任务

//schedule(TimerTask task, Date time) 特定时间执行
    public static void main(String[] args) {
        for (int i = 0; i <20; i++) {
            new Timer("TIMER"+i).schedule(new TimerTask() {
                
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName()+" RUN");
                    
                }
            }, new Date(System.currentTimeMillis()+2000));
        }
    }

View Code

java实现定时任务 java实现定时任务

//schedule(TimerTask task, long delay, long period) 延迟 delay 执行并每隔period 执行一次
    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
           new Timer(" timer"+i).scheduleAtFixedRate(new TimerTask() {
            
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName()+"run");
                
            }
        }, 1000, 2000);    
        }
    }

View Code

ScheduledExecutorService 接口实现类 
ScheduledExecutorService 是JAVA 1.5 后新增的定时任务接口,主要有以下几个方法。

ScheduledFuture<?> schedule(Runnable command,long delay, TimeUnit unit);
 ScheduledFuture<V> schedule(Callable<V> callable,long delay, TimeUnit unit);
 ScheduledFuture<?> scheduleAtFixedRate(Runnable command,long initialDelay,long period,TimeUnitunit);
 ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,long initialDelay,long delay,TimeUnitunit);

默认实现为ScheduledThreadPoolExecutor 继承了ThreadPoolExecutor 的线程池特性,配合future特性,比Timer更强大。 具体用法可以阅读JDK文档;spring Task内部也是依靠它实现的。示例代码:

java实现定时任务 java实现定时任务

public static void main(String[] args) {
        ScheduledExecutorService service=Executors.newSingleThreadScheduledExecutor();
        for (int i = 0; i < 10; i++) {
            service.schedule(new Runnable() {
                
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName() + " run ");
                }
            }, 2, TimeUnit.SECONDS);
        }
        service.shutdown();
        
    }

View Code

  • Quartz 定时器实现

Quartz是一个完全由Java编写的开源作业调度框架,为在Java应用程序中进行作业调度提供了简单却强大的机制。Quartz允许开发人员根据时间间隔来调度作业。它实现了作业和触发器的多对多的关系,还能把多个作业与不同的触发器关联。可以动态的添加删除定时任务,另外很好的支撑集群调度。简单地创建一个org.quarz.Job接口的Java类,Job接口包含唯一的方法:

public void execute(JobExecutionContext context) throws JobExecutionException;

在Job接口实现类里面,添加需要的逻辑到execute()方法中。配置好Job实现类并设定好调度时间表(Trigger),Quartz就会自动在设定的时间调度作业执行execute()。

整合了Quartz的应用程序可以重用不同事件的作业,还可以为一个事件组合多个作业。Quartz通过属性文件来配置JDBC事务的数据源、全局作业、触发器侦听器、插件、线程池等等。(quartz.properties)

通过maven引入依赖(这里主要介绍2.3.0) 注意:shiro-scheduler中依赖的是1.x版本 如果同时使用会冲突

<!-- https://mvnrepository.com/artifact/org.quartz-scheduler/quartz -->
        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz</artifactId>
            <version>2.3.0</version>
        </dependency>

创建Job类

public class TestJob implements Job{
    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        println(Thread.currentThread().getName() + " test job begin " + DateUtil.getCurrentTimeStr());
    }
}

调度任务

public static void main(String[] args) throws InterruptedException, SchedulerException {

        Scheduler scheduler = new StdSchedulerFactory().getScheduler();
        // 开始
        scheduler.start();
        // job 唯一标识 test.test-1
        JobKey jobKey = new JobKey("test" , "test-1");
        JobDetail jobDetail = JobBuilder.newJob(TestJob.class).withIdentity(jobKey).build();
        Trigger trigger = TriggerBuilder.newTrigger()
                .withIdentity("test" , "test")
                // 延迟一秒执行
                .startAt(new Date(System.currentTimeMillis() + 1000))
                // 每隔一秒执行 并一直重复
        .withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(1).repeatForever())
                .build();
        scheduler.scheduleJob(jobDetail , trigger);

        Thread.sleep(5000);
        // 删除job
        scheduler.deleteJob(jobKey);
    }

关于简单使用,可以参考quartz的example,下面链接是一些入门帮助。

Quartz定时任务学习(一)简单任务 
Quartz定时任务学习(二)web应用 
Quartz定时任务学习(三)属性文件和jar

深入学习可以阅读官方文档和相关博客阅读 
以下为推荐博客地址 
quartz详解2:quartz由浅入深  

  • Spring 相关的任务调度

Spring 3.0+ 自带的任务调度实现,主要依靠TaskScheduler接口的几个实现类实现。删除和修改任务比较麻烦。 
主要用法有以下三种:

  • Spring配置文件实现
  • 注解实现
  • 代码动态添加

配置文件实现

spring-schedule.xml

<task:scheduler id="myScheduler" pool-size="10" />
<task:scheduled-tasks scheduler="myScheduler">
    <task:scheduled ref="job" method="test" cron="0 * * * * ?"/>
</task:scheduled-tasks>

注解实现  

spring-schedule.xml
<task:scheduler id="myScheduler" pool-size="10" />
// 启用注解
<task:annotation-driven scheduler="myScheduler"/>

@Component  
public class Task{  

       @Scheduled(cron="0/5 * *  * * ? ")   //每5秒执行一次       
       public void execute(){     
             DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");    
             System.out.println(sdf.format(DateTime.now().toDate())+"*********B任务每5秒执行一次进入测试");      
       }      
}

代码动态添加

spring-schedule.xml

<bean id = "myScheduler" class="org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler">
        <property name="poolSize" value="10"/>
        <property name="threadGroupName" value="myScheduler" />
        <property name="threadNamePrefix" value="-1" />
</bean>
<task:annotation-driven scheduler="myScheduler"/>

@Component
public class Test {

    @Autowired
    private ThreadPoolTaskScheduler myScheduler;

    public void addJob(){

        myScheduler.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + " run ");
            }
        } , new CronTrigger("0/5 * *  * * ? ")); //每5秒执行一次
    }
}

spring 结合 quartz 实现任务调度

  • spring 配置文件 spring-quartz.xml

    com.test.TestJob

动态增加删除  

@Component
public class Test {

    @Autowired
    private SchedulerFactoryBean quartzScheduler;

    public void addJob() throws SchedulerException {

        Scheduler scheduler = quartzScheduler.getScheduler();
        JobKey jobKey = new JobKey("test", "test");
        if (scheduler.checkExists(jobKey)) {
            return;
        }
        JobDetail jobDetail = JobBuilder.newJob(TestJob.class).withIdentity(jobKey).build();
        Trigger trigger = TriggerBuilder.newTrigger().withIdentity("test", "test")
                .withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(1).repeatForever()).build();
        scheduler.scheduleJob(jobDetail, trigger);
    }
}
点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
4个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Stella981 Stella981
3年前
Nginx + lua +[memcached,redis]
精品案例1、Nginxluamemcached,redis实现网站灰度发布2、分库分表/基于Leaf组件实现的全球唯一ID(非UUID)3、Redis独立数据监控,实现订单超时操作/MQ死信操作SelectPollEpollReactor模型4、分布式任务调试Quartz应用
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Docker 部署SpringBoot项目不香吗?
  公众号改版后文章乱序推荐,希望你可以点击上方“Java进阶架构师”,点击右上角,将我们设为★“星标”!这样才不会错过每日进阶架构文章呀。  !(http://dingyue.ws.126.net/2020/0920/b00fbfc7j00qgy5xy002kd200qo00hsg00it00cj.jpg)  2
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Java服务总在半夜挂,背后的真相竟然是... | 京东云技术团队
最近有用户反馈测试环境Java服务总在凌晨00:00左右挂掉,用户反馈Java服务没有定时任务,也没有流量突增的情况,Jvm配置也合理,莫名其妙就挂了
Python进阶者 Python进阶者
10个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这