对于项目中,业务层是必不可少的一环,而除了最基本的对于数据库我们会进行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方法,我们这里使用的是第一个,需要传入两个参数
其中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.大家可以自行了解一下.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。