倒计时 任务调度

迈克丝

对于项目中,业务层是必不可少的一环,而除了最基本的对于数据库我们会进行Dao层的jdbc增删改查操作之外,还会根据项目需求进行各种业务操作,本文主要说一下一种倒计时的业务,类似于购票时对于恶意订单到达时间的自动删除.

而实现任务调度的方式也有很多,本文主要说的是Java中自带的Timer来实现.

1.构建Timer对象

//1.1构建timer对象
Timer timer=new Timer();

第一步是构建Timer对象,这个对象的作用是负责去执行一些调度任务(内置了一个线程和一个任务队列).

2.启动线程执行任务

timer.schedule(new TimerTask() {]\
    @Override
    public void run() {
        System.out.println("执行任务...");
        activityDao.updateState(activity.getId());
        timer.cancel();
    }
}, activity.getEndTime());

如下图所示,Timer的api中有多个schedule方法,我们这里使用的是第一个,需要传入两个参数

image

其中TimerTask为任务对象,其中有一个需要重写的方法(run()),run()方法内就是任务需要执行的内容,一旦调用此任务的线程获得了CPU,就会去执行run()

另一个是指定的时间,这里是activity.getEndTime(),获取的活动对象的结束时间,要达到的目的是,到达设定的活动结束时间,通过dao层的方法将活动的状态置为0也就是无效化.

执行完任务后可以执行timer.cancel(),退出任务调度,线程也就会销毁,解放内存.

3.引出问题

由于我们这里的业务是要在新增活动时,开启这个任务的线程,开始进行倒计时,当达到新增时输入的活动结束时间自动改变状态(也就是state参数),这就出现了一个问题--我们在新增时,一般id都是设为自增的主键,新增时传入的也就是null,那么我们怎么对数据库进行操作改变state的值呢?

这时,由于像新增这种较长的sql语句我们都是在mapper.xml文件中写的-->在<insert>标签中添加-->useGeneratedKeys="true" keyProperty="id"

设置了这两个参数,我们就可以通过getId方法拿到我们需要的id了,代码如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  <mapper namespace="com.cy.pj.activity.dao.ActivityDao">
     <insert id="insertActivity" useGeneratedKeys="true" keyProperty="id" parameterType="com.cy.pj.activity.pojo.Activity">
         insert into tb_activity      (title,category,startTime,endTime,remark,state,createdUser,createdTime) 
         values 
         (#{title},#{category},#{startTime},#{endTime},#{remark},#{state},#{createdUser},now())
     </insert>
  </mapper>

那么,这两个关键的参数究竟是什么含义:

useGeneratedKeys=“true” keyProperty=“id”
useGeneratedKeys设置为 true 时,表示如果插入的表id以自增列为主键,则允许JDBC支持自动生成主键,并可将自动生成的主键id返回。
useGeneratedKeys参数只针对insert语句生效,默认为 false;
keyProperty表示将获得自增主键赋值给参数对象的哪个属性.

当然不只是xml文件中可以使用这两个参数,用注解方式写sql语句也同样可以使用:

需要在@insert注解下加上
@Options(useGeneratedKeys = true,keyProperty = "id")注解即可,含义和xml文件相同.

4.Timer存在问题

Timer只创建唯一的线程来执行所有timer任务.如果一个timer任务的执行很耗时,会导致其他TimerTask的时效准确性出问题.
Timer的另一个问题在于,如果TimerTask抛出未检查的异常,Timer将会产生无法预料的行为.Timer线程并不捕获异常,所以TimerTask抛出的未检查的异常会终止timer线程.这种情况下,Timer也不会再重新恢复线程的执行了;它错误地认为整个Timer被取消了.

这样来看Timer的问题还很严重,业务少的情况还好说,但是真正工作中,业务肯定少不了,所以基本在JDK5.0之后很少有使用Timer了,更多是使用ScheduledExecutor或是第三方框架Quartz.大家可以自行了解一下.

阅读 905

一步一步学技术,踏踏实实涨经验,兴趣广泛,广交好友,希望大家多多指正/批评.

71 声望
5 粉丝
0 条评论

一步一步学技术,踏踏实实涨经验,兴趣广泛,广交好友,希望大家多多指正/批评.

71 声望
5 粉丝
文章目录
宣传栏