对于我的项目中, 业务层是必不可少的一环, 而除了最根本的对于数据库咱们会进行 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. 大家能够自行理解一下.