转:java中的定时任务

引自:http://www.cnblogs.com/wenbronk/p/6433178.html

java中的定时任务, 使用java实现有3种方式:

1, 使用普通thread实现

  @Test
  public void test1() {
        // 单位: 毫秒
        final long timeInterval = 1000;
        Runnable runnable = new Runnable() {
            public void run() {
                while (true) {
                    // ------- code for task to run
                    System.out.println("Hello !!");
                    // ------- ends here
                    try {
                        Thread.sleep(timeInterval);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        };
        Thread thread = new Thread(runnable);
        thread.start();
    } 

2, 使用timer实现: 可控制启动或取消任务, 可指定第一次执行的延迟

  线程安全, 但只会单线程执行, 如果执行时间过长, 就错过下次任务了, 抛出异常时, timerWork会终止

@Test
public void test2 () {
      TimerTask task = new TimerTask() {
          @Override
          public void run() {
             System.out.println("Hello !!!");
          }
      };
      Timer timer = new Timer();
      long delay = 0;
      long intevalPeriod = 1 * 1000;
      // schedules the task to be run in an interval
      timer.scheduleAtFixedRate(task, delay, intevalPeriod);
    }

3, 使用 ScheduledExcecutorService 实现

  ScheduledExecutorService 是java.util.concurrent种的额一个累, 用于实现定时任务

  它可以: 1, 通过线程池的方式执行任务

      2, 设定第一次的延迟事件

      3, 提供良好的约定, 设定时间间隔

@Test
public void test() {
    Runnable runnable = new Runnable() {
            public void run() {
                System.out.println("Hello !!");
            }
        };
        ScheduledExecutorService service = Executors
                .newSingleThreadScheduledExecutor();
        // 第二个参数为首次执行的延时时间,第三个参数为定时执行的间隔时间
        service.scheduleAtFixedRate(runnable, 10, 1, TimeUnit.SECONDS);
    }  

4, 使用spring的 spring-task 实现

   第一种方式, 注解的方式实现

@Target({java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Scheduled
{
  public abstract String cron();  

  public abstract long fixedDelay();  

  public abstract long fixedRate();
}
fixedDelay: 设定间隔时间为 5000ms
fixedRate: 设定固定速率, 以固定速率5s来执行
cron="0 0 2 * * ? ": 使用时间表达式

   第二种方式, 配置文件配置的方式实现

 <task:scheduled-tasks>
        <task:scheduled ref="taskJob" method="job1" cron="0 * * * * ?"/>
</task:scheduled-tasks>
  /* taskJob 为执行任务类, job1 为执行的函数*/
<context:component-scan base-package="com.wenbronk.mytask " />  

    2, 添加配置信息    

<!—开启这个配置,spring才能识别@Scheduled注解   -->
    <task:annotation-driven scheduler="qbScheduler" mode="proxy"/>
    <task:scheduler id="qbScheduler" pool-size="10"/> 

    3, 代码实现 

@Scheduled(fixedDelay = 5000)
public void doSomething() {
    // something that should execute periodically
}

时间表达式

一个cron表达式有至少6个(也可能7个)有空格分隔的时间元素。
按顺序依次为
秒(0~59)
分钟(0~59)
小时(0~23)
天(月)(0~31,但是你需要考虑你月的天数)
月(0~11)
天(星期)(1~7 1=SUN 或 SUN,MON,TUE,WED,THU,FRI,SAT)
年份(1970-2099)

常用的表达式为:

0 0 10,14,16 * * ? 每天上午10点,下午2点,4点
0 0/30 9-17 * * ?   朝九晚五工作时间内每半小时
0 0 12 ? * WED 表示每个星期三中午12点
"0 0 12 * * ?" 每天中午12点触发
"0 15 10 ? * *" 每天上午10:15触发
"0 15 10 * * ?" 每天上午10:15触发
"0 15 10 * * ? *" 每天上午10:15触发
"0 15 10 * * ? 2005" 2005年的每天上午10:15触发
"0 * 14 * * ?" 在每天下午2点到下午2:59期间的每1分钟触发
"0 0/5 14 * * ?" 在每天下午2点到下午2:55期间的每5分钟触发
"0 0/5 14,18 * * ?" 在每天下午2点到2:55期间和下午6点到6:55期间的每5分钟触发
"0 0-5 14 * * ?" 在每天下午2点到下午2:05期间的每1分钟触发
"0 10,44 14 ? 3 WED" 每年三月的星期三的下午2:10和2:44触发
"0 15 10 ? * MON-FRI" 周一至周五的上午10:15触发
"0 15 10 15 * ?" 每月15日上午10:15触发
"0 15 10 L * ?" 每月最后一日的上午10:15触发
"0 15 10 ? * 6L" 每月的最后一个星期五上午10:15触发
"0 15 10 ? * 6L 2002-2005" 2002年至2005年的每月的最后一个星期五上午10:15触发
"0 15 10 ? * 6#3" 每月的第三个星期五上午10:15触发 

5, 使用 第三方插件 Quartz实现

 maven依赖

    <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz</artifactId>
            <version>2.2.1</version>
        </dependency>

5. 1) 可以设置一个类, 继承自 QuartzJobBean

 1, 配置文件:

    <!-- 配置作业类 -->
    <bean name="job1" class="org.springframework.scheduling.quartz.JobDetailBean">
        <property name="jobClass" value="com.gy.Job1" />
        <property name="jobDataAsMap">
            <map>
                <entry key="timeout" value="0" />
            </map>
        </property>
    </bean>

    <!-- 配置触发方式 -->
    <!-- simpleTrggerBean 只支持一种方式调度 -->
    <bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">
        <property name="jobDetail" ref="job1" />
        <property name="startDelay" value="0" />  <!-- 调度工厂实例化后,经过0秒开始执行调度 -->
        <property name="repeatInterval" value="2000" />  <!-- 每2秒调度一次 -->
    </bean>

    <!-- 使用CronTrggerBean , 支持时间表达式 -->
    <bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
        <property name="jobDetail" ref="job1" />
        <!-- 每天12点运行一次 -->
        <property name="cronExpression" value="0 0 12 * * ?" />
    </bean>

  2, 配置调度工厂:

    <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        <property name="triggers">
            <list>
                <ref bean="cronTrigger" />
            </list>
        </property>
    </bean>

   3, 定义作业类:

public class Job1 extends QuartzJobBean {
        private int timeout;
        private static int i = 0;
        // 调度工厂实例化后,经过timeout时间开始执行调度
        public void setTimeout(int timeout) {
            this.timeout = timeout;
        }
        /**
         * 要调度的具体任务
         */
        @Override
        protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
            System.out.println("定时任务执行中…");
        }
    }

5.2) 直接写一个普通类, 在配置中进行配置

  任务类:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;

/**
 * 定时删除用户收听过的poi
 * @author wenbronk
 * @time 2017年3月28日  下午2:01:09  2017
 */
public class DelListenerPOIScheduler {

    @Autowired
    private StringRedisTemplate redisTemplate;

    public void doCheck() {
        System.out.println("定时任务执行了....");
    }

}

配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
                        http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
                        http://www.springframework.org/schema/tx
                        http://www.springframework.org/schema/tx/spring-tx-4.2.xsd
                        http://www.springframework.org/schema/aop
                        http://www.springframework.org/schema/aop/spring-aop-4.2.xsd
                        http://www.springframework.org/schema/aop
                        http://www.springframework.org/schema/aop/spring-aop-4.2.xsd
                        http://www.springframework.org/schema/mvc
                         http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd
                        http://www.springframework.org/schema/context
                        http://www.springframework.org/schema/context/spring-context-4.2.xsd">

    <!-- 配置作业类 -->
    <bean id="delRedisListenerHistory" class="com.iwhere.easy.travel.valid.DelListenerPOIScheduler" />

    <!-- 作业类描述, 使用方法调度 -->
    <bean id="methodInvoking"
        class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
        <property name="targetObject" ref="delRedisListenerHistory" />
        <property name="targetMethod" value="doCheck" />
    </bean>

    <!-- 触发器, 使用定时触发 -->
    <bean id="delTrigger"
        class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
        <property name="jobDetail" ref="methodInvoking" />
        <property name="cronExpression" value="0/10 * * * * ?" />
    </bean>

    <!-- 总调度器 -->
    <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        <property name="triggers">
            <list>
                <ref bean="delTrigger" />
            </list>
        </property>
    </bean>

</beans>

6, 在springboot中实现定时任务:

package com.iwhere.base.scheduling;

import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;

/**
 * 整合定时任务
 * EnableScheduling 实现spring中的task功能
 * @Scheduled中配置时间表达式
 * @author 231
 *
 */
@Configuration        // 相当于配置beans,
@EnableScheduling    // <task:*>, 让spring进行任务调度
public class SchedulingConfig {

    @Scheduled(cron="0/20 * * * * ?")    // 20秒执行一次
    public void scheduler() {
        System.out.println("定时任务执行了");
    }

}

7, Springboot 集成 quartz

为什么非要集成呢, 因为quartz支持集群定时任务, 现在还用不到, 防止以后用到

1, 配置quartz的配置信息类

package com.iwhere.easy.travel.timeschedule;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.CronTriggerFactoryBean;
import org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
/**
 * quartz的配置信息
 * @author wenbronk
 * @time 2017年3月29日  下午5:20:29  2017
 */
@Configuration
public class TimeScheduleConfig {

    @Bean(name = "detailFactoryBean")
    public MethodInvokingJobDetailFactoryBean detailFactoryBean(DelListenerPOIScheduler scheduledTasks) {
        MethodInvokingJobDetailFactoryBean bean = new MethodInvokingJobDetailFactoryBean();
        // 这儿设置对应的Job对象
        bean.setTargetObject(scheduledTasks);
        // 这儿设置对应的方法名 与执行具体任务调度类中的方法名对应
        bean.setTargetMethod("doCheck");
        bean.setConcurrent(false);
        return bean;
    }

    @Bean(name = "cronTriggerBean")
    public CronTriggerFactoryBean cronTriggerBean(MethodInvokingJobDetailFactoryBean detailFactoryBean) {
        CronTriggerFactoryBean trigger = new CronTriggerFactoryBean();
        trigger.setJobDetail(detailFactoryBean.getObject());
        try {
            trigger.setCronExpression("0 0 1 * * ?");// 每天1点执行一次
        } catch (Exception e) {
            e.printStackTrace();
        }
        return trigger;

    }

    @Bean
    public SchedulerFactoryBean schedulerFactory(CronTriggerFactoryBean cronTriggerBean) {
        SchedulerFactoryBean schedulerFactory = new SchedulerFactoryBean();
        schedulerFactory.setTriggers(cronTriggerBean.getObject());
        return schedulerFactory;
    }

}

2), 具体的作业类

package com.iwhere.easy.travel.timeschedule;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.stereotype.Component;

/**
 * 定时删除用户收听过的poi
 * @author wenbronk
 * @time 2017年3月28日  下午2:01:09  2017
 */
@Component
@Configurable
@EnableScheduling
public class DelListenerPOIScheduler {
    private Logger LOGGER = LoggerFactory.getLogger(DelListenerPOIScheduler.class);

    @Autowired
    private StringRedisTemplate redisTemplate;

    public void doCheck() {

        try {
            String key = "noteUserListenedPoi:*";
            redisTemplate.delete(key);
            LOGGER.info("redis中用户收听历史被清空");
        } catch (Exception e) {
            e.printStackTrace();
            LOGGER.error("redis删除用户收听记录失败");
        }
    }

}

系列原创, 转载请注明出处, 谢谢 @Wenbronk: http://www.cnblogs.com/wenbronk/p/6433178.html

原文地址:https://www.cnblogs.com/x-jingxin/p/10640862.html

时间: 2024-08-29 13:35:10

转:java中的定时任务的相关文章

java中quartz定时任务的执行如何避免并发

在执行定时任务的时候,把定时任务的时间设置为10分钟执行一次,由于数据量很大,第一个十分钟还没执行结束,第二个十分钟已经开始了,这样就造成了并发,但是又不想用 java中的锁,这样很纠结,在网上找了好多资料 其实很简单,我们只要在detail的参数里加上一句话就行了,把这个job设置成有状态的job <property name="concurrent" value="false" /> ③ 指定最终封装出的任务是否有状态 通过concurrent属性指

Java中的定时任务

现代的应用程序早已不是以前的那些由简单的增删改查拼凑而成的程序了,高复杂性早已是标配,而任务的定时调度与执行也是对程序的基本要求了. 很多业务需求的实现都离不开定时任务,例如,每月一号,移动将清空你上月未用完流量,重置套餐流量,以及备忘录提醒.闹钟等功能. Java 系统中主要有三种方式来实现定时任务: Timer和TimerTask ScheduledExecutorService 三方框架 Quartz 下面我们一个个来看. Timer和TimerTask 先看一个小 demo,接着我们再来

java中实现定时功能

网上资料: 我们可以使用Timer和TimerTask类在java中实现定时任务,详细说明如下: 1.基础知识java.util.Timer一种线程设施,用于安排以后在后台线程中执行的任务.可安排任务执行一次,或者定期重复执行.此类是线程安全的:多个线程可以共享单个 Timer 对象而无需进行外部同步.java.util.TimerTask由 Timer 安排为一次执行或重复执行的任务. 2.示例代码该示例实现这样一个功能,在系统运行期间,每30分钟,系统自动检查连接池中的可用连接数,并输出到日

定时任务:Java中Timer和TimerTask的使用

java.util.Timer定时器,实际上是个线程,定时调度所拥有的TimerTasks. 一个TimerTask实际上就是一个拥有run方法的类,需要定时执行的代码放到run方法体内,TimerTask一般是以匿名类的方式创建. 一个完整的Timer: Java代码   java.util.Timer timer = new java.util.Timer(true); // true 说明这个timer以daemon方式运行(优先级低, // 程序结束timer也自动结束),注意,java

如何用 Java 实现 Web 应用中的定时任务

定时任务,是指定一个未来的时间范围执行一定任务的功能.在当前WEB应用中,多数应用都具备任务调度功能,针对不同的语音,不同的操作系统, 都有其自己的语法及解决方案,windows操作系统把它叫做任务计划,linux中cron服务都提供了这个功能,在我们开发业务系统中很多时候会涉及到这个功能.本场chat将使用java语言完成日常开发工作中常用定时任务的使用,希望给大家工作及学习带来帮助. 一.定时任务场景 (1)驱动处理工作流程 作为一个新的预支付订单被初始化放置,如果该订单在指定时间内未进行支

Java之旅--定时任务(Timer、Quartz、Spring、LinuxCron)

在Java中,实现定时任务有多种方式.本文介绍4种.Timer和TimerTask.Spring.QuartZ.Linux Cron. 以上4种实现定时任务的方式.Timer是最简单的.不须要不论什么框架,只JDK就能够.缺点是不过个时间间隔的定时器,调度简单.Spring和QuartZ都支持cron,功能都非常强大,Spring的长处是略微简单一点,QuartZ的长处是没有Spring也可使用:Linux Cron是个操作系统级别的定时任务.适用于全部操作系统支持的语言,缺点是精度只能到达分钟

spring项目中的定时任务实现和问题解决

之前我用JAVA中的Timer类实现了服务器的定时任务,具体详见之前的博文. 后来发现了一个更简单的实现方式,利用spring中的@Scheduled注解实现觉得简单的很多. 确实spring封装的特别好,实现起来比原来简单多了. 下面是配置. 在spring的xml配置中最上面加入 xmlns:task=http://www.springframework.org/schema/task xsi:schemaLocation中加入 http://www.springframework.org/

Java中那些踩过的坑

仅以此随笔记录一些在java中踩过而且又重踩的坑 _(:з)∠)_ 1. Runnable In ScheduledExecutorsService 当使用ScheduledExecutorService, Runnable内没有捕获的RuntimeException将会使Executor停止运行,并且异常不会被输出. ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(); schedu

web项目中添加定时任务

1.在web.xml中添加servlet <servlet> <servlet-name>StatisticInitServlet</servlet-name> <servlet-class>com.jovision.servlet.StatisticInitServlet</servlet- class> <load-on-startup>1</load-on-startup> 该servlet加载顺序,设为1,数字越小